PAL Portal (J2 デスクトップの調査)

jetspeed.loadPortletWindowsから見てみましょ。

jetspeed.loadPortletWindows = function( portletWindowFactory )
{
if ( jetspeed.prefs.windowTiling > 0 )
{
var numberOfColumns = jetspeed.page.getNumberOfColumns();
jetspeed.ui.createColumns( document.getElementById( jetspeed.id.DESKTOP ), numberOfColumns );
}
var windowsToRender = [];
var portletArray = jetspeed.page.getPortletArrayByColumnRow();
jetspeed.ui._loadPortletWindows( portletArray, windowsToRender, portletWindowFactory );
portletArray = jetspeed.page.getPortletArrayByZIndex();
jetspeed.ui._loadPortletWindows( portletArray, windowsToRender, portletWindowFactory );
if ( windowsToRender && windowsToRender.length > 0 )
{
jetspeed.doRenderAll( null, windowsToRender, true );
}
jetspeed.page.retrieveAllMenus();   // BOZO: should not be happening here!
};

あ、jetspeed.prefsについて、確認し忘れていたので、ここで確認しておこう。jetspeed.initializeDesktopから使っていたね・・・(^^;

jetspeed.prefs =
{
windowTiling: 2,     // number > 0 is interpreted as number of columns; 0 or false indicates no-columns, free-floating windows
windowTilingVariableWidth: false,   // only meaningful when windowTiling > 0
windowTilingVariableHeight: true,   // only meaningful when windowTiling > 0
//portalTaskBarType: "blee"  // BOZO: need pref/s to handle this ( instead of html elements in the content )
defaultPortletWidth: "280",
defaultPortletHeight: "200",
desktopTheme: null,
desktopThemeRootUrl: null,
getDesktopTheme: function()
{
if ( jetspeed.prefs.desktopTheme == null )
return djConfig.desktopTheme;
return jetspeed.prefs.desktopTheme;
},
getDesktopThemeRootUrl: function()
{
if ( jetspeed.prefs.desktopThemeRootUrl == null )
return djConfig.desktopThemeRootUrl;
return jetspeed.prefs.desktopThemeRootUrl;
},
portletSelectorWindowTitle: "Portlet Selector",
portletSelectorWindowIcon: "text-x-script.png",
portletSelectorBounds: { x: 20, y: 20, width: 400, height: 600 }
};

windowTilingにはデフォルトで2を与えているのね・・・。ポートレットの幅と高さもこんなところにあるな。

windowTilingは2だから、getNumberOfColumnsに入って、

getNumberOfColumns: function()
{
var numberOfColumns = 1;
if ( this.columns != null )
return this.columns;
var portletArray = this.getPortletArray();
if ( ! portletArray ) return portletArray;
var filteredPortletArray = [];
for ( var i = 0 ; i < portletArray.length; i++ )
{
if ( portletArray[i].getProperty( jetspeed.id.PORTLET_PROP_WINDOW_POSITION_STATIC ) )
{
var windowState = portletArray[i].getLastSavedWindowState();
if ( windowState && windowState.column != null && (windowState.column + 1) > numberOfColumns )
numberOfColumns = new Number( windowState.column ) + 1;
}
}
return numberOfColumns;
},

columnsはnullだから、下の処理にいって、ポートレットの配列の中から位置の固定のものをチェックしていくのね。ポートレットのgetLastSavedWindowState()は、

getLastSavedWindowState: function()
{
if ( ! this.lastSavedWindowState )
this._initializeWindowState();
return this.lastSavedWindowState;
},

で、lastSavedWindowStateはセットされていないから、_initializeWindowStateに行って、

_initializeWindowState: function( /* boolean */ reset )
{
var initialWindowState = {};
var windowPositionStatic = this.getProperty( jetspeed.id.PORTLET_PROP_WINDOW_POSITION_STATIC );
var portletWidth = this.getProperty( "width" );
if ( ! reset && portletWidth != null && portletWidth > 0 )
initialWindowState.width = Math.floor( portletWidth );
else if ( reset )
initialWindowState.width = -1;
var portletHeight = this.getProperty( "height" );
if ( ! reset && portletHeight != null && portletHeight > 0  )
initialWindowState.height = Math.floor( portletHeight );
else if ( reset )
initialWindowState.height = -1;
if ( ! windowPositionStatic )
{
var portletLeft = this.getProperty( "x" );
if ( ! reset && portletLeft != null && portletLeft >= 0 )
initialWindowState.left = Math.floor( ( (portletLeft > 0) ? portletLeft : 0 ) );
else if ( reset )
initialWindowState.left = -1;
var portletTop = this.getProperty( "y" );
if ( ! reset && portletTop != null && portletTop >= 0 )
initialWindowState.top = Math.floor( ( (portletTop > 0) ? portletTop : 0 ) );
else
initialWindowState.top = -1;
var portletZIndex = this.getProperty( "z" );
if ( ! reset && portletZIndex != null && portletZIndex >= 0 )
initialWindowState.zIndex = Math.floor( portletZIndex );
else if ( reset )
initialWindowState.zIndex = -1;
}
else
{
var portletColumn = this.getProperty( jetspeed.id.PORTLET_PROP_COLUMN );
initialWindowState.column = portletColumn;
var portletRow = this.getProperty( jetspeed.id.PORTLET_PROP_ROW );
initialWindowState.row = portletRow;
}
if ( jetspeed.debug.initializeWindowState )
{
if ( ! windowPositionStatic )
dojo.debug( "initializeWindowState [" + this.entityId + "] z=" + initialWindowState.zIndex + " x=" + initialWindowState.left + " y=" + initialWindowState.top + " width=" + initialWindowState.width + " height=" + initialWindowState.height );
else
dojo.debug( "initializeWindowState [" + this.entityId + "] column=" + initialWindowState.column + " row=" + initialWindowState.row + " width=" + initialWindowState.width + " height=" + initialWindowState.height );
}
this.lastSavedWindowState = initialWindowState;
return initialWindowState;
},

何の処理かを見ると、高さと幅をセットして、場所が固定であれば、行と列をセットし、そうでなければ、x,y,z の位置情報をセットする。値は、initialWindowStateに保持するのね。まぁ、最後の方のはデバッグで表示するかだな。そんで、lastSavedWindowStateにもコピーしておくのだね。っでgetNumberOfColumnsに戻る。

getNumberOfColumnsのwindowStateは、ポートレットウィンドウの場所情報のinitialWindowStateが入って、getNumberOfColumnsよりwindowState.column+1が大きかったら、getNumberOfColumnsにwindowState.column+1を入れるのね。はて、なぜ、+1 より大きくする必要があるのだろうか?単純に column の最大値が入れば良さそうな気もするけど。ループの比較で使うからかな??

引き続き見ていくと、

if ( jetspeed.prefs.windowTiling > 0 )
{
var numberOfColumns = jetspeed.page.getNumberOfColumns();
jetspeed.ui.createColumns( document.getElementById( jetspeed.id.DESKTOP ), numberOfColumns );
}

だから、numberOfColumns に得た値を入れて、createColumns で、まず、columnsParent にドキュメント上の id がjetspeedDesktopとなっている要素を渡している。たとえば、blue.jspを見ると以下のような感じ。

<div class="<%= desktopThemeStyleClass %>" id="jetspeedDesktop"></div>

そんで、2番目のcolumnTotalにはさっき取得したnumberOfColumnsが入って、

jetspeed.ui.createColumns = function( columnsParent, columnTotal )
{
if ( columnTotal > 0 )
{
jetspeed.columns = new Array( columnTotal );
var columnContainer = document.createElement( "div" );
columnContainer.id = jetspeed.id.COLUMNS;
for ( var i = 0 ; i < columnTotal ; i++ )
{
jetspeed.ui.createColumn( columnContainer, i, columnTotal );
}
columnsParent.appendChild( columnContainer );
}
};

jetspeed.columnsの配列を作って、jetspeedDesktopをidとして持つタグに対して、div タグで id にjetspeed.id.COLUMNS(値はjetspeedColumns)をセットしたタグを最終的にappendChildで貼り付けるのね。ループ内のcreateColumnを見てみると、

jetspeed.ui.createColumn = function( columnContainer, columnIndex, columnTotal )
{
var divElmt = document.createElement("div");
divElmt.setAttribute("columnIndex", columnIndex);
var colWidthPctg = Math.round(100/columnTotal);
if ( columnIndex == (columnTotal-1) && ( (columnTotal * colWidthPctg) >= 100 ) )
colWidthPctg = colWidthPctg -1;
divElmt.style.width = colWidthPctg + "%";
divElmt.style.minHeight = "1px";
divElmt.className = "DesktopColumn";
jetspeed.columns[columnIndex]  = divElmt;
columnContainer.appendChild(divElmt);
//divElmt.appendChild( document.createTextNode( "LayoutColumn" + (columnIndex +1) ) );
};

div タグを作って、columnIndex属性に0から始める番号を与えて、100をcolumnTotalで割った値を%として、幅として与える。そんで、そのタグのクラス名にDesktopColumnを与えて、jetspeed.columns配列に入れておく(操作しやすいようにかね)。そんで、先ほど作った、親の div タグに貼り付ける。というわけで、ここまでで、表示するためのレイアウトとなるタグを表示するHTMLに貼り付けたわけだね。そして、jetspeed.loadPortletWindowsにもどる。

var windowsToRender = [];
var portletArray = jetspeed.page.getPortletArrayByColumnRow();

次の処理は、getPortletArrayByColumnRowで

getPortletArrayByColumnRow: function()
{
var portletArray = this.getPortletArray();
if ( ! portletArray ) return portletArray;
var filteredPortletArray = [];
for ( var i = 0 ; i < portletArray.length; i++ )
{
var posStatic = portletArray[i].getProperty( jetspeed.id.PORTLET_PROP_WINDOW_POSITION_STATIC );
var colSpan = portletArray[i].getProperty( jetspeed.id.PORTLET_PROP_COLUMN_SPAN );
if ( posStatic || colSpan != null )
{
filteredPortletArray.push( portletArray[i] );
}
}
filteredPortletArray.sort( this._portletColumnRowCompare );
return filteredPortletArray;
},

ここでは、登録されたポートレット配列で列情報をもち、場所が固定じゃないものをfilteredPortletArray配列に入れていき、入れ終わったところで、sortを実行。その比較の際に使われるのが、

_portletColumnRowCompare: function( portletA, portletB )
{   // uses saved state only - does not check with window widget
var windowState = portletA.getLastSavedWindowState();
var col = ( windowState.column == null ? 50 : windowState.column );
var row = ( windowState.row == null ? 0 : windowState.row );
var aVal = ( col * 1000 ) + row;
windowState = portletB.getLastSavedWindowState();
col = ( windowState.column == null ? 50 : windowState.column );
row = ( windowState.row == null ? 0 : windowState.row );
var bVal = ( col * 1000 ) + row;
return ( aVal - bVal );
},

で、( col * 1000 ) + row というのが比較の際の基準だね。ソートして、jetspeed.loadPortletWindowsに戻って、portletArrayにその配列を渡す。

次は、

jetspeed.ui._loadPortletWindows( portletArray, windowsToRender, portletWindowFactory );

で、windowsToRenderは空の配列で、portletWindowsFactoryはnullかね。

今日はここまで・・・。

PAL Portal (J2 デスクトップの調査)

続き・・・

jetspeed.page.retrievePsml();を見てみよう。まず、pageContentListenerにnew jetspeed.om.PageContentListenerCreateWidget()を与える(と思われる、null だから)。PageContentListenerCreateWidget()は、

// ... jetspeed.om.PageContentListenerCreateWidget
jetspeed.om.PageContentListenerCreateWidget = function()
{
};
jetspeed.om.PageContentListenerCreateWidget.prototype =
{
notifySuccess: function( /* XMLDocument */ data, /* String */ requestUrl, /* Page */ page )
{
page.getPortletsFromPSML( data );
jetspeed.loadPortletWindows();
},
notifyFailure: function( /* String */ type, /* String */ error, /* String */ requestUrl, /* Page */ page )
{
dojo.raise( "PageContentListenerCreateWidget notifyFailure url=" + requestUrl + " type=" + type + " error=" + error ) ;
}
};

と言う感じで、コンストラクタ?では何もしない。メソッドとして、notifySuccessとnotifyFailureを持っている。この段階では、これらのメソッドは関係ないと思うけど。

っで、次にretrievePsml()でpsmlUrlとmimeTypeを取得する。psmlUrlのgetPsmlUrl()は以下のような感じ。

getPsmlUrl: function()
{
if ( this.psmlPath == null )
this.setPsmlPathFromDocumentUrl() ;
return jetspeed.url.basePortalUrl() + this.psmlPath ;
},

この段階では、psmlPathはnullだろうから、

setPsmlPathFromDocumentUrl: function()
{
var psmlPath = jetspeed.url.path.AJAX_API ;
var docPath = document.location.pathname ;
var contextAndServletPath = jetspeed.url.path.DESKTOP ;
var contextAndServletPathPos = docPath.indexOf( contextAndServletPath ) ;
if ( contextAndServletPathPos != -1 && docPath.length > ( contextAndServletPathPos + contextAndServletPath.length ) )
{
psmlPath = psmlPath + docPath.substring( contextAndServletPathPos + contextAndServletPath.length ) ;
}
this.psmlPath = psmlPath ;
},

psmlPathはAJAX用のパス名をセットしている(たとえば、/palportal/ajaxかな)。docPathは現在のURLのパス名でそれに対して、jetspeed.url.path.DESKTOPは/palportal/desktopのようなものだから、それのindexOfを取ろうとしている。docPathが長ければ、psmlPathにそれをくっつけて、最終的なpsmlPathにしているみたいだな。

getPsmlUrlに戻って、jetspeed.url.basePortalUrl()をくっつけて、return して、psmlUrlの完成 🙂 ちなみにbasePortalUrl()は

jetspeed.url.basePortalUrl = function()
{
if ( ! jetspeed.url.path.initialized )
jetspeed.url.pathInitialize();
return jetspeed.url.path.SERVER;    // return document.location.protocol + "//" + document.location.host ;
};

と言う感じで、既にjetspeed.url.path.initializedはtrueだから、単純にjetspeed.url.path.SERVERを返してくる。この値は、http://localhost:8080/palportalみたいな感じかな。

そんで、jetspeed.url.retrieveContentへGo!

jetspeed.url.retrieveContent = function( requestUrl, contentListener, formObject, mimeType, domainModelObject, debugContentDumpIds )
{
if ( ! requestUrl )
{
dojo.raise( "retrieveContent null requestUrl is illegal" );
return;
}
if ( ! mimeType )
mimeType = "text/html";
dojo.io.bind({
url: requestUrl,
formNode: formObject,
mimetype: mimeType,
load: function( type, data, evt )
{
//dojo.debug( "loaded content for url: " + this.url );
//dojo.debug( "r e t r i e v e C o n t e n t . l o a d" ) ;
//dojo.debug( "  type:" );
//dojo.debugShallow( type ) ;
//dojo.debug( "  evt:" );
//dojo.debugShallow( evt ) ;
if ( debugContentDumpIds )
{
var dmId = ( ( domainModelObject && dojo.lang.isFunction( domainModelObject.getId ) ) ? domainModelObject.getId() : "" );
for ( var debugContentIndex = 0 ; debugContentIndex < debugContentDumpIds.length; debugContentIndex++ )
{
if ( dmId.match( new RegExp( debugContentDumpIds[ debugContentIndex ] ) ) )
{
if ( dojo.lang.isString( data ) )
dojo.debug( "retrieveContent [" + ( dmId ? dmId : requestUrl ) + "] content: " + data );
else
{
var textContent = dojo.dom.innerXML( data );
if ( ! textContent )
textContent = ( data != null ? "!= null (IE no XMLSerializer)" : "null" );
dojo.debug( "retrieveContent [" + ( dmId ? dmId : requestUrl ) + "] xml-content: " + textContent );
}
}
}
}
if ( contentListener && dojo.lang.isFunction( contentListener.notifySuccess ) )
{
contentListener.notifySuccess( data, requestUrl, domainModelObject ) ;
}
else
{
dojo.debug( "retrieveContent [" + ( dmId ? dmId : requestUrl ) + "] no valid contentListener" );
}
},
error: function( type, error )
{
//dojo.debug( "r e t r i e v e C o n t e n t . e r r o r" ) ;
//dojo.debug( "  type:" );
//dojo.debugShallow( type ) ;
//dojo.debug( "  error:" );
//dojo.debugShallow( error ) ;
if ( contentListener && dojo.lang.isFunction( contentListener.notifyFailure ) )
{
contentListener.notifyFailure( type, error, requestUrl, domainModelObject );
}
}
});
};

これは、ちょっと長いな・・・。でも、見てみると、requestUrlとmimeTypeをチェックして、dojo.io.bindの呼び出しか。dojo.io.bind内のdebugContentDumpIdsのブロックはデバッグコードっぽいから、まぁ、ここでは読み飛ばすとして、アクセスに成功すると、contentListener.notifySuccessになるのか。これは、前述したnotifySuccessだね。引数は、アクセスして帰ってきたデータ、アクセスしたURL(PSML の URL)、domainModelObjectはjetspeed.url.retrieveContentを呼び出したjetspeed.om.Pageのインスタンスだね。というわけで、

notifySuccess: function( /* XMLDocument */ data, /* String */ requestUrl, /* Page */ page )
{
page.getPortletsFromPSML( data );
jetspeed.loadPortletWindows();
},

に戻る(今回はアクセス失敗時の動作は追わないでおこ)。dojo.io.bindについては http://manual.dojotoolkit.org/io.html を参照。

では、まず、getPortletsFromPSMLを見てみましょ。

getPortletsFromPSML: function( psml )
{
var pageElements = psml.getElementsByTagName( "page" );
if ( ! pageElements || pageElements.length > 1 )
dojo.raise( "unexpected zero or multiple <page> elements in psml" );
var pageElement = pageElements[0];
var children = pageElement.childNodes;
var simpleValueLNames = new RegExp( "(name|path|title|short-title)" );
for ( var i = 0 ; i < children.length ; i++ )
{
var child = children[i];
if ( child.nodeType != dojo.dom.ELEMENT_NODE )
continue;
var childLName = child.nodeName;
if ( childLName == "defaults" )
{
this.layoutDecorator = child.getAttribute( "layout-decorator" );
this.portletDecorator = child.getAttribute( "portlet-decorator" );
}
else if ( childLName && childLName.match( simpleValueLNames  ) )
{
this[ jetspeed.purifyIdentifier( childLName, "", "lo" ) ] = ( ( child && child.firstChild ) ? child.firstChild.nodeValue : null );
}
}
var lis = pageElement.getElementsByTagName( "fragment" );
for( var x=0; x < lis.length; x++ )
{
var fragType = lis[x].getAttribute( "type" );
if ( fragType == "portlet" )
{
var portletName = lis[x].getAttribute( "name" );
var portletEntityId = lis[x].getAttribute( "id" );
var portlet = new jetspeed.om.Portlet( portletName, portletEntityId ) ;
var props = lis[x].getElementsByTagName( "property" );
for( var propsIdx=0; propsIdx < props.length; propsIdx++ )
{
var propName = props[propsIdx].getAttribute( "name" ) ;
var propValue = props[propsIdx].getAttribute( "value" ) ;
portlet.putProperty( propName, propValue ) ;
}
portlet.initialize();
this.putPortlet( portlet ) ;
}
}
},

dojo.io.bindで取った、data は、XMLDocumentになるのね。帰ってくるPSMLデータについては、 http://jetspeed-japan.sourceforge.jp/jetspeed-2-trans/ja/guides/guide-ajax-api.html を参照。

getPortletsFromPSMLを見て、現状の問題点に気づく。まず、title の meta タグが無視されているので、ページのタイトルが国際化されない。あとは、25%,75%の2列のレイアウトを選んでも、2列に表示されるが50%,50%くらいに表示されるな~っと思っていたら、ここで、無視していたからなのね。

内容についてみてみると、前半部分ではページに関する情報を取得しているだけだね(まぁ、あとで、meta タグの処理をいれんといかんけど)。後半部分では、各ポートレット情報の取得だな。portletName と portletEntityIdをセットして、jetspeed.om.Portlet を作成している。portletName は、たとえば、blog::BlogTitleViewPortletみたいな感じで、portletEntityId はフラグメントの ID だから、ポータル全体でユニークな値だね。次にjetspeed.om.Portletは

jetspeed.om.Portlet = function( /* String */ portletName, /* String */ portletEntityId, /* special */ alternateContentRetriever )
{
this.name = portletName;
this.entityId = portletEntityId;
this.properties = {};
if ( alternateContentRetriever )
this.contentRetriever = alternateContentRetriever;
};

だから、name, entityId と使う properties を作成して、alternateContentRetriever をセットするみたいだね。ここでは、alternateContentRetriever はなしと思われる。というわけで、getPortletsFromPSMLに戻る。

var props = lis[x].getElementsByTagName( "property" );
for( var propsIdx=0; propsIdx < props.length; propsIdx++ )
{
var propName = props[propsIdx].getAttribute( "name" ) ;
var propValue = props[propsIdx].getAttribute( "value" ) ;
portlet.putProperty( propName, propValue ) ;
}

っで、fragmentタグ内にあるpropertyタグを処理していくのだね。propertyタグのnameとvalue属性を順番にportletインスタンスに入れていっている。ちなみに、Portlet クラスの putProperty は

putProperty: function(name, value)
{
this.properties[name] = value;
},

と言う感じで、properties に入れていっているだけだね。そして、getPortletsFromPSMLでは、次に、portlet.initialize();を呼び出しとるね。

initialize: function()
{   // must be called once init sensitive putProperty calls are complete
if ( ! this.getProperty( jetspeed.id.PORTLET_PROP_WIDGET_ID ) )
{
this.putProperty( jetspeed.id.PORTLET_PROP_WIDGET_ID, jetspeed.id.PORTLET_WINDOW_ID_PREFIX + this.entityId );
}
if ( ! this.getProperty( jetspeed.id.PORTLET_PROP_CONTENT_RETRIEVER ) )
{
this.putProperty( jetspeed.id.PORTLET_PROP_CONTENT_RETRIEVER, this.contentRetriever );
}
var colSpan = this.getProperty( jetspeed.id.PORTLET_PROP_COLUMN_SPAN );
if ( colSpan != null )
{
if ( ! jetspeed.prefs.windowTiling || ! dojo.lang.isNumber( colSpan ) || colSpan <= 1 )
{
colSpan = null ;
this.putProperty( jetspeed.id.PORTLET_PROP_COLUMN_SPAN, null );
}
}
var posStatic = this.getProperty( jetspeed.id.PORTLET_PROP_WINDOW_POSITION_STATIC );
if ( posStatic != null && posStatic && ( ! jetspeed.prefs.windowTiling || colSpan != null ) )
{
posStatic = false ;
this.putProperty( jetspeed.id.PORTLET_PROP_WINDOW_POSITION_STATIC, false );
}
else if ( posStatic == null )
{
if ( jetspeed.prefs.windowTiling )
this.putProperty( jetspeed.id.PORTLET_PROP_WINDOW_POSITION_STATIC, true );
else
this.putProperty( jetspeed.id.PORTLET_PROP_WINDOW_POSITION_STATIC, false );
}
var windowtitle = this.getProperty( jetspeed.id.PORTLET_PROP_WINDOW_TITLE );
if ( ! windowtitle && this.name )
{
var re = (/^[^:]*:*/);
windowtitle = this.name.replace( re, "" );
this.putProperty( jetspeed.id.PORTLET_PROP_WINDOW_TITLE, windowtitle );
}
},

ここでは、いくつか定数があるな・・・。これを見る前にjetspeed.idを確認。

jetspeed.id =
{
DESKTOP: "jetspeedDesktop",
TASKBAR: "jetspeedTaskbar",
COLUMNS: "jetspeedColumns",
SELECTOR: "jetspeedSelector",
PORTLET_STYLE_CLASS: "portlet",
PORTLET_WINDOW_STYLE_CLASS: "dojoFloatingPane",
PORTLET_WINDOW_GHOST_STYLE_CLASS: "ghostPane",
PORTLET_WINDOW_ID_PREFIX: "portletWindow_",
PORTLET_PROP_WIDGET_ID: "widgetId",
PORTLET_PROP_CONTENT_RETRIEVER: "contentRetriever",
PORTLET_PROP_WINDOW_POSITION_STATIC: "windowPositionStatic",
PORTLET_PROP_COLUMN_SPAN: "windowColumnSpan",
PORTLET_PROP_WINDOW_THEME: "windowTheme",
PORTLET_PROP_WINDOW_TITLE: "title",
PORTLET_PROP_WINDOW_ICON: "windowIcon",
PORTLET_PROP_WIDTH: "width",
PORTLET_PROP_HEIGHT: "height",
PORTLET_PROP_LEFT: "left",
PORTLET_PROP_TOP: "top",
PORTLET_PROP_COLUMN: "column",
PORTLET_PROP_ROW: "row",
PORTLET_PROP_EXCLUDE_PCONTENT: "excludePContent",
PORTLET_PROP_WINDOW_STATE: "windowState",
MENU_WIDGET_ID_PREFIX: "jetspeed-menu-",
WINDOW_THEMES: [ "tigris", "blueocean" ]     // temporary validation to avoid trying to use an undefined window theme
};

initializeを見てみると、初期設定という感じだな。jetspeed.id.PORTLET_PROP_WIDGET_IDはIDだな。jetspeed.id.PORTLET_PROP_CONTENT_RETRIEVERは、デフォルトの値が入ると思われるから、

dojo.inherits( jetspeed.om.Portlet, jetspeed.om.Id);
dojo.lang.extend( jetspeed.om.Portlet,
{
name: null,
entityId: null,
contentRetriever: new jetspeed.om.PortletContentRetriever(),
windowFactory: null,
lastSavedWindowState: null,
JAVASCRIPT_ACTION_PREFIX: "javascript:doAction(",
JAVASCRIPT_RENDER_PREFIX: "javascript:doRender(",
JAVASCRIPT_ARG_QUOTE: "&" + "quot;",
PORTLET_REQUEST_ACTION: "action",
PORTLET_REQUEST_RENDER: "render",

にあるjetspeed.om.PortletContentRetriever()だな。コンストラクタでは、何もしていないみたい。

jetspeed.om.PortletContentRetriever = function()
{
};

と言う感じでjetspeed.id.PORTLET_PROP_CONTENT_RETRIEVERが決定。

jetspeed.id.PORTLET_PROP_COLUMN_SPANはfragementタグのpropertyタグに値があれば、それを使うけど、変な値があれば、nullにしているっぽい。そんで、jetspeed.id.PORTLET_PROP_WINDOW_POSITION_STATICは、場所を固定するかどうかだな。これもpsmlで設定できるのか・・・。jetspeed.id.PORTLET_PROP_WINDOW_TITLEはその名の通り、タイトルかね。これまた、psmlでできるのかね?でも、デフォルトだと、タイトルはポートレット名から取得している。ポートレットのインスタンスからはとらんのか?あとで、セットしているのかもしれんけど。

そして、getPortletsFromPSML間で戻って、portlet.initialize()の次は、putPortletは、

putPortlet: function( /* Portlet */ portlet )
{
if (!portlet) return ;
if (! this.portlets) this.portlets = [] ;
this.portlets[ portlet.entityId ] = portlet ;
},

portlets配列がなければ、作成して、ポートレットインスタンスを格納。

ふ~、これで、getPortletsFromPSMLが終わった・・・。つまりのところ、こいつで、ポートレット情報の取得と初期化だな。で、次は、notifySuccessまで戻って、jetspeed.loadPortletWindows();だそうな。

今日のところはこれまで・・・

PAL Portal (J2 デスクトップの調査)

続き・・・

jetspeed.loadDebugWindow();はデバッグメッセージの出力用ウィンドウの表示だから、良いとして、jetspeed.page.retrievePsml();は以下のような感じ。

retrievePsml: function( pageContentListener )
{
if ( pageContentListener == null )
pageContentListener = new jetspeed.om.PageContentListenerCreateWidget();
var psmlUrl = this.getPsmlUrl() ;
var mimeType = "text/xml";
if ( jetspeed.debug.retrievePsml )
dojo.debug( "retrievePsml url: " + psmlUrl ) ;
jetspeed.url.retrieveContent( psmlUrl, pageContentListener, null, mimeType, this, jetspeed.debugContentDumpIds );    },

今日も時間切れ・・・