result = this.contentNodes;
-
- // we clear the member variable during invalidateComponents()
-
- return result;
- }
-
- /**
- * Setup the common properties required at data-binding time.
- *
- * These are properties used by components on the page when iterating over the nodes.
- * The properties are available as the Node is a Map so they can be accessed directly
- * by name. Information such as download URL, size and filetype are provided etc.
- *
- * We use a set of anonymous inner classes to provide the implemention for the property
- * getters. The interfaces are only called when the properties are first requested.
- *
- * @param node Node to add the properties too
- */
- public void setupCommonBindingProperties(Node node)
- {
- // special properties to be used by the value binding components on the page
- node.addPropertyResolver("url", this.resolverUrl);
- node.addPropertyResolver("webdavUrl", this.resolverWebdavUrl);
- node.addPropertyResolver("cifsPath", this.resolverCifsPath);
- node.addPropertyResolver("fileType16", this.resolverFileType16);
- node.addPropertyResolver("fileType32", this.resolverFileType32);
- node.addPropertyResolver("size", this.resolverSize);
- }
-
-
- // ------------------------------------------------------------------------------
- // IContextListener implementation
-
- /**
- * @see org.alfresco.web.app.context.IContextListener#contextUpdated()
- */
- public void contextUpdated()
- {
- invalidateComponents();
- }
-
-
- // ------------------------------------------------------------------------------
- // NodeEventListener listeners
-
- /**
- * Add a listener to those called by the BrowseBean when nodes are created
- */
- public void addNodeEventListener(NodeEventListener listener)
- {
- getNodeEventListeners().add(listener);
- }
-
- /**
- * Remove a listener from the list of those called by BrowseBean
- */
- public void removeNodeEventListener(NodeEventListener listener)
- {
- getNodeEventListeners().remove(listener);
- }
-
-
- // ------------------------------------------------------------------------------
- // Navigation action event handlers
-
- /**
- * Change the current view mode based on user selection
- *
- * @param event ActionEvent
- */
- public void viewModeChanged(ActionEvent event)
- {
- UIModeList viewList = (UIModeList)event.getComponent();
-
- // get the view mode ID
- String viewMode = viewList.getValue().toString();
-
- if (VIEWMODE_DASHBOARD.equals(viewMode) == false)
- {
- // set the page size based on the style of display
- int pageSize = this.viewsConfig.getDefaultPageSize(PAGE_NAME_BROWSE, viewMode);
- setPageSizeContent(pageSize);
- setPageSizeSpaces(pageSize);
-
- if (logger.isDebugEnabled())
- logger.debug("Browse view page size set to: " + pageSize);
-
- setDashboardView(false);
-
- // push the view mode into the lists
- setBrowseViewMode(viewMode);
-
- navigateBrowseScreen();
- }
- else
- {
- // special case for Dashboard view
- setDashboardView(true);
- }
- }
-
-
- // ------------------------------------------------------------------------------
- // Helper methods
-
- /**
- * Query a list of nodes for the specified parent node Id
- *
- * @param parentNodeId Id of the parent node or null for the root node
- */
- private void queryBrowseNodes(String parentNodeId)
- {
- long startTime = 0;
- if (logger.isDebugEnabled())
- startTime = System.currentTimeMillis();
-
- UserTransaction tx = null;
- try
- {
- FacesContext context = FacesContext.getCurrentInstance();
- tx = Repository.getUserTransaction(context, true);
- tx.begin();
-
- NodeRef parentRef;
- if (parentNodeId == null)
- {
- // no specific parent node specified - use the root node
- parentRef = this.nodeService.getRootNode(Repository.getStoreRef());
- }
- else
- {
- // build a NodeRef for the specified Id and our store
- parentRef = new NodeRef(Repository.getStoreRef(), parentNodeId);
- }
-
- List childRefs = this.nodeService.getChildAssocs(parentRef,
- ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
- this.containerNodes = new ArrayList(childRefs.size());
- this.contentNodes = new ArrayList(childRefs.size());
- for (ChildAssociationRef ref: childRefs)
- {
- // create our Node representation from the NodeRef
- NodeRef nodeRef = ref.getChildRef();
-
- if (this.nodeService.exists(nodeRef))
- {
- // find it's type so we can see if it's a node we are interested in
- QName type = this.nodeService.getType(nodeRef);
-
- // make sure the type is defined in the data dictionary
- TypeDefinition typeDef = this.dictionaryService.getType(type);
-
- if (typeDef != null)
- {
- MapNode node = null;
-
- // look for Space folder node
- if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_FOLDER) == true &&
- this.dictionaryService.isSubClass(type, ContentModel.TYPE_SYSTEM_FOLDER) == false)
- {
- // create our Node representation
- node = new MapNode(nodeRef, this.nodeService, true);
- node.addPropertyResolver("icon", this.resolverSpaceIcon);
- node.addPropertyResolver("smallIcon", this.resolverSmallIcon);
-
- this.containerNodes.add(node);
- }
- // look for File content node
- else if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT))
- {
- // create our Node representation
- node = new MapNode(nodeRef, this.nodeService, true);
- setupCommonBindingProperties(node);
-
- this.contentNodes.add(node);
- }
- // look for File Link object node
- else if (ContentModel.TYPE_FILELINK.equals(type))
- {
- // create our File Link Node representation
- node = new MapNode(nodeRef, this.nodeService, true);
- node.addPropertyResolver("url", this.resolverLinkUrl);
- node.addPropertyResolver("webdavUrl", this.resolverLinkWebdavUrl);
- node.addPropertyResolver("cifsPath", this.resolverLinkCifsPath);
- node.addPropertyResolver("fileType16", this.resolverFileType16);
- node.addPropertyResolver("fileType32", this.resolverFileType32);
- node.addPropertyResolver("size", this.resolverSize);
-
- this.contentNodes.add(node);
- }
- else if (ContentModel.TYPE_FOLDERLINK.equals(type))
- {
- // create our Folder Link Node representation
- node = new MapNode(nodeRef, this.nodeService, true);
- node.addPropertyResolver("icon", this.resolverSpaceIcon);
- node.addPropertyResolver("smallIcon", this.resolverSmallIcon);
-
- this.containerNodes.add(node);
- }
-
- // inform any listeners that a Node wrapper has been created
- if (node != null)
- {
- for (NodeEventListener listener : getNodeEventListeners())
- {
- listener.created(node, type);
- }
- }
- }
- else
- {
- if (logger.isEnabledFor(Priority.WARN))
- logger.warn("Found invalid object in database: id = " + nodeRef + ", type = " + type);
- }
- }
- }
-
- // commit the transaction
- tx.commit();
- }
- catch (InvalidNodeRefException refErr)
- {
- Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
- FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {refErr.getNodeRef()}) );
- this.containerNodes = Collections.emptyList();
- this.contentNodes = Collections.emptyList();
- try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
- }
- catch (Throwable err)
- {
- Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
- FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
- this.containerNodes = Collections.emptyList();
- this.contentNodes = Collections.emptyList();
- try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
- }
-
- if (logger.isDebugEnabled())
- {
- long endTime = System.currentTimeMillis();
- logger.debug("Time to query and build map nodes: " + (endTime - startTime) + "ms");
- }
- }
-
- /**
- * Search for a list of nodes using the specific search context
- *
- * @param searchContext To use to perform the search
- */
- private void searchBrowseNodes(SearchContext searchContext)
- {
- long startTime = 0;
- if (logger.isDebugEnabled())
- startTime = System.currentTimeMillis();
-
- // get the searcher object to build the query
- String query = searchContext.buildQuery(getMinimumSearchLength());
- if (query == null)
- {
- // failed to build a valid query, the user probably did not enter the
- // minimum text required to construct a valid search
- Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), MSG_SEARCH_MINIMUM),
- new Object[] {getMinimumSearchLength()}));
- this.containerNodes = Collections.emptyList();
- this.contentNodes = Collections.emptyList();
- return;
- }
-
- // perform the search against the repo
- UserTransaction tx = null;
- ResultSet results = null;
- try
- {
- tx = Repository.getUserTransaction(FacesContext.getCurrentInstance(), true);
- tx.begin();
-
- // Limit search to the first 100 matches
- SearchParameters sp = new SearchParameters();
- sp.setLanguage(SearchService.LANGUAGE_LUCENE);
- sp.setQuery(query);
- sp.addStore(Repository.getStoreRef());
-
- int searchLimit = Application.getClientConfig(FacesContext.getCurrentInstance()).getSearchMaxResults();
- if(searchLimit > 0)
- {
- sp.setLimitBy(LimitBy.FINAL_SIZE);
- sp.setLimit(searchLimit);
- }
-
- results = this.searchService.query(sp);
- if (logger.isDebugEnabled())
- logger.debug("Search results returned: " + results.length());
-
- // create a list of items from the results
- this.containerNodes = new ArrayList(results.length());
- this.contentNodes = new ArrayList(results.length());
- if (results.length() != 0)
- {
- for (ResultSetRow row: results)
- {
- NodeRef nodeRef = row.getNodeRef();
-
- if (this.nodeService.exists(nodeRef))
- {
- // find it's type so we can see if it's a node we are interested in
- QName type = this.nodeService.getType(nodeRef);
-
- // make sure the type is defined in the data dictionary
- TypeDefinition typeDef = this.dictionaryService.getType(type);
-
- if (typeDef != null)
- {
- MapNode node = null;
-
- // look for Space or File nodes
- if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_FOLDER) &&
- this.dictionaryService.isSubClass(type, ContentModel.TYPE_SYSTEM_FOLDER) == false)
- {
- // create our Node representation
- node = new MapNode(nodeRef, this.nodeService, false);
-
- node.addPropertyResolver("path", this.resolverPath);
- node.addPropertyResolver("displayPath", this.resolverDisplayPath);
- node.addPropertyResolver("icon", this.resolverSpaceIcon);
- node.addPropertyResolver("smallIcon", this.resolverSmallIcon);
-
- this.containerNodes.add(node);
- }
- else if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT))
- {
- // create our Node representation
- node = new MapNode(nodeRef, this.nodeService, false);
-
- setupCommonBindingProperties(node);
-
- node.addPropertyResolver("path", this.resolverPath);
- node.addPropertyResolver("displayPath", this.resolverDisplayPath);
-
- this.contentNodes.add(node);
- }
- // look for File Link object node
- else if (ContentModel.TYPE_FILELINK.equals(type))
- {
- // create our File Link Node representation
- node = new MapNode(nodeRef, this.nodeService, false);
- node.addPropertyResolver("url", this.resolverLinkUrl);
- node.addPropertyResolver("webdavUrl", this.resolverLinkWebdavUrl);
- node.addPropertyResolver("cifsPath", this.resolverLinkCifsPath);
- node.addPropertyResolver("fileType16", this.resolverFileType16);
- node.addPropertyResolver("fileType32", this.resolverFileType32);
- node.addPropertyResolver("size", this.resolverSize);
- node.addPropertyResolver("path", this.resolverPath);
- node.addPropertyResolver("displayPath", this.resolverDisplayPath);
-
- this.contentNodes.add(node);
- }
- else if (ContentModel.TYPE_FOLDERLINK.equals(type))
- {
- // create our Folder Link Node representation
- node = new MapNode(nodeRef, this.nodeService, false);
- node.addPropertyResolver("icon", this.resolverSpaceIcon);
- node.addPropertyResolver("smallIcon", this.resolverSmallIcon);
- node.addPropertyResolver("path", this.resolverPath);
- node.addPropertyResolver("displayPath", this.resolverDisplayPath);
-
- this.containerNodes.add(node);
- }
-
- // inform any listeners that a Node wrapper has been created
- if (node != null)
- {
- for (NodeEventListener listener : getNodeEventListeners())
- {
- listener.created(node, type);
- }
- }
- }
- else
- {
- if (logger.isEnabledFor(Priority.WARN))
- logger.warn("Found invalid object in database: id = " + nodeRef + ", type = " + type);
- }
- }
- else
- {
- if (logger.isEnabledFor(Priority.WARN))
- logger.warn("Missing object returned from search indexes: id = " + nodeRef + " search query: " + query);
- }
- }
- }
-
- // commit the transaction
- tx.commit();
- }
- catch (InvalidNodeRefException refErr)
- {
- Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
- FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {refErr.getNodeRef()}) );
- this.containerNodes = Collections.emptyList();
- this.contentNodes = Collections.emptyList();
- try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
- }
- catch (Throwable err)
- {
- logger.info("Search failed for: " + query);
- Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
- FacesContext.getCurrentInstance(), Repository.ERROR_SEARCH), new Object[] {err.getMessage()}), err );
- this.containerNodes = Collections.emptyList();
- this.contentNodes = Collections.emptyList();
- try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
- }
- finally
- {
- if (results != null)
- {
- results.close();
- }
- }
-
- if (logger.isDebugEnabled())
- {
- long endTime = System.currentTimeMillis();
- logger.debug("Time to query and build map nodes: " + (endTime - startTime) + "ms");
- }
- }
-
-
- // ------------------------------------------------------------------------------
- // Property Resolvers
-
- public NodePropertyResolver resolverDownload = new NodePropertyResolver() {
- public Object get(Node node) {
- return DownloadContentServlet.generateDownloadURL(node.getNodeRef(), node.getName());
- }
- };
-
- public NodePropertyResolver resolverUrl = new NodePropertyResolver() {
- public Object get(Node node) {
- return DownloadContentServlet.generateBrowserURL(node.getNodeRef(), node.getName());
- }
- };
-
- public NodePropertyResolver resolverWebdavUrl = new NodePropertyResolver() {
- public Object get(Node node) {
- return Utils.generateURL(FacesContext.getCurrentInstance(), node, URLMode.WEBDAV);
- }
- };
-
- public NodePropertyResolver resolverCifsPath = new NodePropertyResolver() {
- public Object get(Node node) {
- return Utils.generateURL(FacesContext.getCurrentInstance(), node, URLMode.CIFS);
- }
- };
-
- public NodePropertyResolver resolverLinkDownload = new NodePropertyResolver() {
- public Object get(Node node) {
- NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION);
- if (nodeService.exists(destRef) == true)
- {
- String destName = Repository.getNameForNode(nodeService, destRef);
- return DownloadContentServlet.generateDownloadURL(node.getNodeRef(), destName);
- }
- else
- {
- // TODO: link object is missing - navigate to a page with appropriate message
- return "#";
- }
- }
- };
-
- public NodePropertyResolver resolverLinkUrl = new NodePropertyResolver() {
- public Object get(Node node) {
- NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION);
- if (nodeService.exists(destRef) == true)
- {
- String destName = Repository.getNameForNode(nodeService, destRef);
- return DownloadContentServlet.generateBrowserURL(destRef, destName);
- }
- else
- {
- // TODO: link object is missing - navigate to a page with appropriate message
- return "#";
- }
- }
- };
-
- public NodePropertyResolver resolverLinkWebdavUrl = new NodePropertyResolver() {
- public Object get(Node node) {
- NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION);
- if (nodeService.exists(destRef) == true)
- {
- return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.WEBDAV);
- }
- else
- {
- // TODO: link object is missing - navigate to a page with appropriate message
- return "#";
- }
- }
- };
-
- public NodePropertyResolver resolverLinkCifsPath = new NodePropertyResolver() {
- public Object get(Node node) {
- NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION);
- if (nodeService.exists(destRef) == true)
- {
- return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.CIFS);
- }
- else
- {
- // TODO: link object is missing - navigate to a page with appropriate message
- return "#";
- }
- }
- };
-
- public NodePropertyResolver resolverFileType16 = new NodePropertyResolver() {
- public Object get(Node node) {
- return Utils.getFileTypeImage(node.getName(), true);
- }
- };
-
- public NodePropertyResolver resolverFileType32 = new NodePropertyResolver() {
- public Object get(Node node) {
- return Utils.getFileTypeImage(node.getName(), false);
- }
- };
-
- public NodePropertyResolver resolverPath = new NodePropertyResolver() {
- public Object get(Node node) {
- return nodeService.getPath(node.getNodeRef());
- }
- };
-
- public NodePropertyResolver resolverDisplayPath = new NodePropertyResolver() {
- public Object get(Node node) {
- // TODO: replace this with a method that shows the full display name - not QNames?
- return Repository.getDisplayPath( (Path)node.getProperties().get("path") );
- }
- };
-
- public NodePropertyResolver resolverSpaceIcon = new NodePropertyResolver() {
- public Object get(Node node) {
- QNameNodeMap props = (QNameNodeMap)node.getProperties();
- String icon = (String)props.getRaw("app:icon");
- return (icon != null ? icon : CreateSpaceWizard.DEFAULT_SPACE_ICON_NAME);
- }
- };
-
- public NodePropertyResolver resolverSmallIcon = new NodePropertyResolver() {
- public Object get(Node node) {
- QNameNodeMap props = (QNameNodeMap)node.getProperties();
- String icon = (String)props.getRaw("app:icon");
- return (icon != null ? icon + "-16" : SPACE_SMALL_DEFAULT);
- }
- };
-
- public NodePropertyResolver resolverMimetype = new NodePropertyResolver() {
- public Object get(Node node) {
- ContentData content = (ContentData)node.getProperties().get(ContentModel.PROP_CONTENT);
- return (content != null ? content.getMimetype() : null);
- }
- };
-
- public NodePropertyResolver resolverSize = new NodePropertyResolver() {
- public Object get(Node node) {
- ContentData content = (ContentData)node.getProperties().get(ContentModel.PROP_CONTENT);
- return (content != null ? new Long(content.getSize()) : 0L);
- }
- };
-
-
- // ------------------------------------------------------------------------------
- // Navigation action event handlers
-
- /**
- * Action called from the Simple Search component.
- * Sets up the SearchContext object with the values from the simple search menu.
- */
- public void search(ActionEvent event)
- {
- // setup the search text string on the top-level navigation handler
- UISimpleSearch search = (UISimpleSearch)event.getComponent();
- this.navigator.setSearchContext(search.getSearchContext());
-
- navigateBrowseScreen();
- }
-
- /**
- * Action called to Close the search dialog by returning to the last view node Id
- */
- public void closeSearch(ActionEvent event)
- {
- // set the current node Id ready for page refresh
- this.navigator.setCurrentNodeId( this.navigator.getCurrentNodeId() );
- }
-
- /**
- * Update page size based on user selection
- */
- public void updateSpacesPageSize(ActionEvent event)
- {
- try
- {
- int size = Integer.parseInt(this.pageSizeSpacesStr);
- if (size >= 0)
- {
- this.pageSizeSpaces = size;
- }
- else
- {
- // reset to known value if this occurs
- this.pageSizeSpacesStr = Integer.toString(this.pageSizeSpaces);
- }
- }
- catch (NumberFormatException err)
- {
- // reset to known value if this occurs
- this.pageSizeSpacesStr = Integer.toString(this.pageSizeSpaces);
- }
- }
-
- /**
- * Update page size based on user selection
- */
- public void updateContentPageSize(ActionEvent event)
- {
- try
- {
- int size = Integer.parseInt(this.pageSizeContentStr);
- if (size >= 0)
- {
- this.pageSizeContent = size;
- }
- else
- {
- // reset to known value if this occurs
- this.pageSizeContentStr = Integer.toString(this.pageSizeContent);
- }
- }
- catch (NumberFormatException err)
- {
- // reset to known value if this occurs
- this.pageSizeContentStr = Integer.toString(this.pageSizeContent);
- }
- }
-
- /**
- * Action called when a folder space is clicked.
- * Navigate into the space.
- */
- public void clickSpace(ActionEvent event)
- {
- UIActionLink link = (UIActionLink)event.getComponent();
- Map params = link.getParameterMap();
- String id = params.get("id");
- if (id != null && id.length() != 0)
- {
- try
- {
- NodeRef ref = new NodeRef(Repository.getStoreRef(), id);
-
- // handle special folder link node case
- if (ContentModel.TYPE_FOLDERLINK.equals(this.nodeService.getType(ref)))
- {
- ref = (NodeRef)this.nodeService.getProperty(ref, ContentModel.PROP_LINK_DESTINATION);
- }
-
- clickSpace(ref);
- }
- catch (InvalidNodeRefException refErr)
- {
- Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
- FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {id}) );
- }
- }
- }
-
- /**
- * Action called when a folder space is clicked.
- *
- * @param nodeRef The node being clicked
- */
- public void clickSpace(NodeRef nodeRef)
- {
- // refresh UI based on node selection
- updateUILocation(nodeRef);
- }
-
- /**
- * Handler called when a path element is clicked - navigate to the appropriate Space
- */
- public void clickSpacePath(ActionEvent event)
- {
- UINodePath.PathElementEvent pathEvent = (UINodePath.PathElementEvent)event;
- NodeRef ref = pathEvent.NodeReference;
- try
- {
- // refresh UI based on node selection
- this.updateUILocation(ref);
- }
- catch (InvalidNodeRefException refErr)
- {
- Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
- FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {ref.getId()}) );
- }
- }
-
- /**
- * Action called when a folders direct descendant (in the 'list' browse mode) is clicked.
- * Navigate into the the descendant space.
- */
- public void clickDescendantSpace(ActionEvent event)
- {
- UINodeDescendants.NodeSelectedEvent nodeEvent = (UINodeDescendants.NodeSelectedEvent)event;
- NodeRef nodeRef = nodeEvent.NodeReference;
- if (nodeRef == null)
- {
- throw new IllegalStateException("NodeRef returned from UINodeDescendants.NodeSelectedEvent cannot be null!");
- }
-
- if (logger.isDebugEnabled())
- logger.debug("Selected noderef Id: " + nodeRef.getId());
-
- try
- {
- // user can either select a descendant of a node display on the page which means we
- // must add the it's parent and itself to the breadcrumb
- ChildAssociationRef parentAssocRef = nodeService.getPrimaryParent(nodeRef);
-
- if (logger.isDebugEnabled())
- {
- logger.debug("Selected item getPrimaryParent().getChildRef() noderef Id: " + parentAssocRef.getChildRef().getId());
- logger.debug("Selected item getPrimaryParent().getParentRef() noderef Id: " + parentAssocRef.getParentRef().getId());
- logger.debug("Current value getNavigator().getCurrentNodeId() noderef Id: " + this.navigator.getCurrentNodeId());
- }
-
- if (nodeEvent.IsParent == false)
- {
- // a descendant of the displayed node was selected
- // first refresh based on the parent and add to the breadcrumb
- updateUILocation(parentAssocRef.getParentRef());
-
- // now add our selected node
- updateUILocation(nodeRef);
- }
- else
- {
- // else the parent ellipses i.e. the displayed node was selected
- updateUILocation(nodeRef);
- }
- }
- catch (InvalidNodeRefException refErr)
- {
- Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
- FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {nodeRef.getId()}) );
- }
- }
-
- /**
- * Action event called by all Browse actions that need to setup a Space context
- * before an action page/wizard is called. The context will be a Node in setActionSpace() which
- * can be retrieved on the action page from BrowseBean.getActionSpace().
- *
- * @param event ActionEvent
- */
- public void setupSpaceAction(ActionEvent event)
- {
- UIActionLink link = (UIActionLink)event.getComponent();
- Map params = link.getParameterMap();
- String id = params.get("id");
- setupSpaceAction(id, true);
- }
-
- /**
- * Public helper to setup action pages with Space context
- *
- * @param id of the Space node to setup context for
- */
- public void setupSpaceAction(String id, boolean invalidate)
- {
- if (id != null && id.length() != 0)
- {
- if (logger.isDebugEnabled())
- logger.debug("Setup for action, setting current space to: " + id);
-
- try
- {
- // create the node ref, then our node representation
- NodeRef ref = new NodeRef(Repository.getStoreRef(), id);
- Node node = new Node(ref);
-
- // resolve icon in-case one has not been set
- node.addPropertyResolver("icon", this.resolverSpaceIcon);
-
- // prepare a node for the action context
- setActionSpace(node);
-
- // setup the dispatch context in case it is required
- this.navigator.setupDispatchContext(node);
- }
- catch (InvalidNodeRefException refErr)
- {
- Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
- FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {id}) );
- }
- }
- else
- {
- setActionSpace(null);
- }
-
- // clear the UI state in preparation for finishing the next action
- if (invalidate == true)
- {
- // use the context service to notify all registered beans
- UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans();
- }
- }
-
- /**
- * Acrtion event called by Delete Space actions. We setup the action space as normal, then prepare
- * any special case message string to be shown to the user if they are trying to delete specific spaces.
- */
- public void setupDeleteAction(ActionEvent event)
- {
- String message = null;
-
- setupSpaceAction(event);
-
- Node node = getActionSpace();
- if (node != null)
- {
- NodeRef companyRootRef = new NodeRef(Repository.getStoreRef(), Application.getCompanyRootId());
- if (node.getNodeRef().equals(companyRootRef))
- {
- message = Application.getMessage(FacesContext.getCurrentInstance(), MSG_DELETE_COMPANYROOT);
- }
- }
-
- setDeleteMessage(message);
- }
-
- /**
- * Action event called by all actions that need to setup a Content Document context on the
- * BrowseBean before an action page/wizard is called. The context will be a Node in
- * setDocument() which can be retrieved on the action page from BrowseBean.getDocument().
- */
- public void setupContentAction(ActionEvent event)
- {
- UIActionLink link = (UIActionLink)event.getComponent();
- Map params = link.getParameterMap();
- setupContentAction(params.get("id"), true);
- }
-
- /**
- * Public helper to setup action pages with content context
- *
- * @param id of the content node to setup context for
- */
- public void setupContentAction(String id, boolean invalidate)
- {
- if (id != null && id.length() != 0)
- {
- if (logger.isDebugEnabled())
- logger.debug("Setup for action, setting current document to: " + id);
-
- try
- {
- // create the node ref, then our node representation
- NodeRef ref = new NodeRef(Repository.getStoreRef(), id);
- Node node = new Node(ref);
-
- // store the URL to for downloading the content
- if (ContentModel.TYPE_FILELINK.equals(node.getType()))
- {
- node.addPropertyResolver("url", this.resolverLinkDownload);
- }
- else
- {
- node.addPropertyResolver("url", this.resolverDownload);
- }
- node.addPropertyResolver("fileType32", this.resolverFileType32);
- node.addPropertyResolver("mimetype", this.resolverMimetype);
- node.addPropertyResolver("size", this.resolverSize);
-
- for (NodeEventListener listener : getNodeEventListeners())
- {
- listener.created(node, node.getType());
- }
-
- // get hold of the DocumentDetailsBean and reset it
- DocumentDetailsBean docDetails = (DocumentDetailsBean)FacesContext.getCurrentInstance().
- getExternalContext().getSessionMap().get("DocumentDetailsBean");
- if (docDetails != null)
- {
- docDetails.reset();
- }
-
- // remember the document
- setDocument(node);
-
- // setup the dispatch context in case it is required
- this.navigator.setupDispatchContext(node);
- }
- catch (InvalidNodeRefException refErr)
- {
- Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
- FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {id}) );
- }
- }
- else
- {
- setDocument(null);
- }
-
- // clear the UI state in preparation for finishing the next action
- if (invalidate == true)
- {
- // use the context service to notify all registered beans
- UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans();
- }
- }
-
- /**
- * Removes the given node from the breadcrumb i.e. following a delete
- *
- * @param node The space to remove from the breadcrumb
- */
- public void removeSpaceFromBreadcrumb(Node node)
- {
- List location = navigator.getLocation();
- IBreadcrumbHandler handler = location.get(location.size() - 1);
- if (handler instanceof BrowseBreadcrumbHandler)
- {
- // see if the current breadcrumb location is our node
- if ( ((BrowseBreadcrumbHandler)handler).getNodeRef().equals(node.getNodeRef()) == true )
- {
- location.remove(location.size() - 1);
-
- // now work out which node to set the list to refresh against
- if (location.size() != 0)
- {
- handler = location.get(location.size() - 1);
- if (handler instanceof BrowseBreadcrumbHandler)
- {
- // change the current node Id
- navigator.setCurrentNodeId(((BrowseBreadcrumbHandler)handler).getNodeRef().getId());
- }
- else
- {
- // TODO: shouldn't do this - but for now the user home dir is the root!
- navigator.setCurrentNodeId(Application.getCurrentUser(FacesContext.getCurrentInstance()).getHomeSpaceId());
- }
- }
- }
- }
- }
-
- /**
- * Support for refresh of lists via special case for an External Access URL.
- * these URLs restart the JSF lifecycle but an old UIRichList is restored from
- * the component tree - which needs clearing "late" in the lifecycle process.
- */
- public void externalAccessRefresh()
- {
- this.externalForceRefresh = true;
- }
-
-
- // ------------------------------------------------------------------------------
- // Private helpers
-
- /**
- * Initialise default values from client configuration
- */
- private void initFromClientConfig()
- {
- ConfigService config = Application.getConfigService(FacesContext.getCurrentInstance());
-
- this.viewsConfig = (ViewsConfigElement)config.getConfig("Views").
- getConfigElement(ViewsConfigElement.CONFIG_ELEMENT_ID);
-
- this.browseViewMode = this.viewsConfig.getDefaultView(PAGE_NAME_BROWSE);
- int pageSize = this.viewsConfig.getDefaultPageSize(PAGE_NAME_BROWSE, this.browseViewMode);
- setPageSizeContent(pageSize);
- setPageSizeSpaces(pageSize);
- }
-
- /**
- * @return the Set of NodeEventListeners registered against this bean
- */
- private Set getNodeEventListeners()
- {
- if (this.nodeEventListeners == null)
- {
- this.nodeEventListeners = new HashSet();
-
- FacesContext fc = FacesContext.getCurrentInstance();
-
- Config listenerConfig = Application.getConfigService(fc).getConfig("Node Event Listeners");
- if (listenerConfig != null)
- {
- ConfigElement listenerElement = listenerConfig.getConfigElement("node-event-listeners");
- if (listenerElement != null)
- {
- for (ConfigElement child : listenerElement.getChildren())
- {
- if (child.getName().equals("listener"))
- {
- // retrieved the JSF Managed Bean identified in the config
- String listenerName = child.getValue().trim();
- Object bean = FacesHelper.getManagedBean(fc, listenerName);
- if (bean instanceof NodeEventListener)
- {
- addNodeEventListener((NodeEventListener)bean);
- }
- }
- }
- }
- }
- }
- return this.nodeEventListeners;
- }
-
- /**
- * Refresh the UI after a Space selection change. Adds the selected space to the breadcrumb
- * location path and also updates the list components in the UI.
- *
- * @param ref NodeRef of the selected space
- */
- public void updateUILocation(NodeRef ref)
- {
- // get the current breadcrumb location and append a new handler to it
- // our handler know the ID of the selected node and the display label for it
- List location = this.navigator.getLocation();
- if (location.size() != 0)
- {
- // attempt to find the ID - if it's already in the breadcrumb then we
- // navigate directly to that node - rather than add duplication to the breadcrumb path
- boolean foundNode = false;
- for (int i=0; i newLocation = new ArrayList(i+1);
- //newLocation.addAll(location.subList(0, i + 1));
- //this.navigator.setLocation(newLocation);
- // TODO: but instead for now we do this:
- int count = location.size();
- for (int n=i+1; n nodeEventListeners = null;
-
- /** Component references */
- protected UIRichList spacesRichList;
- protected UIRichList contentRichList;
- private UIStatusMessage statusMessage;
-
- /** Transient lists of container and content nodes for display */
- private List containerNodes = null;
- private List contentNodes = null;
-
- /** The current space and it's properties - if any */
- private Node actionSpace;
-
- /** The current document */
- private Node document;
-
- /** Special message to display when user deleting certain folders e.g. Company Home */
- private String deleteMessage;
-
- /** The current browse view mode - set to a well known IRichListRenderer identifier */
- private String browseViewMode;
-
- /** The current browse view page sizes */
- private int pageSizeSpaces;
- private int pageSizeContent;
- private String pageSizeSpacesStr;
- private String pageSizeContentStr;
-
- /** True if current space has a dashboard (template) view available */
- private boolean dashboardView;
-
- private boolean externalForceRefresh = false;
-}
+/*
+ * Copyright (C) 2005 Alfresco, Inc.
+ *
+ * Licensed under the Mozilla Public License version 1.1
+ * with a permitted attribution clause. You may obtain a
+ * copy of the License at
+ *
+ * http://www.alfresco.org/legal/license.txt
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the
+ * License.
+ */
+package org.alfresco.web.bean;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ActionEvent;
+import javax.transaction.UserTransaction;
+
+import org.alfresco.config.Config;
+import org.alfresco.config.ConfigElement;
+import org.alfresco.config.ConfigService;
+import org.alfresco.model.ContentModel;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.dictionary.TypeDefinition;
+import org.alfresco.service.cmr.lock.LockService;
+import org.alfresco.service.cmr.model.FileFolderService;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.ContentData;
+import org.alfresco.service.cmr.repository.InvalidNodeRefException;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.Path;
+import org.alfresco.service.cmr.search.LimitBy;
+import org.alfresco.service.cmr.search.ResultSet;
+import org.alfresco.service.cmr.search.ResultSetRow;
+import org.alfresco.service.cmr.search.SearchParameters;
+import org.alfresco.service.cmr.search.SearchService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.service.namespace.RegexQNamePattern;
+import org.alfresco.web.app.AlfrescoNavigationHandler;
+import org.alfresco.web.app.Application;
+import org.alfresco.web.app.context.IContextListener;
+import org.alfresco.web.app.context.UIContextService;
+import org.alfresco.web.app.servlet.DownloadContentServlet;
+import org.alfresco.web.app.servlet.FacesHelper;
+import org.alfresco.web.bean.repository.MapNode;
+import org.alfresco.web.bean.repository.Node;
+import org.alfresco.web.bean.repository.NodePropertyResolver;
+import org.alfresco.web.bean.repository.QNameNodeMap;
+import org.alfresco.web.bean.repository.Repository;
+import org.alfresco.web.bean.spaces.CreateSpaceWizard;
+import org.alfresco.web.config.ViewsConfigElement;
+import org.alfresco.web.ui.common.Utils;
+import org.alfresco.web.ui.common.Utils.URLMode;
+import org.alfresco.web.ui.common.component.IBreadcrumbHandler;
+import org.alfresco.web.ui.common.component.UIActionLink;
+import org.alfresco.web.ui.common.component.UIBreadcrumb;
+import org.alfresco.web.ui.common.component.UIModeList;
+import org.alfresco.web.ui.common.component.UIStatusMessage;
+import org.alfresco.web.ui.common.component.UIPanel.ExpandedEvent;
+import org.alfresco.web.ui.common.component.data.UIRichList;
+import org.alfresco.web.ui.repo.component.IRepoBreadcrumbHandler;
+import org.alfresco.web.ui.repo.component.UINodeDescendants;
+import org.alfresco.web.ui.repo.component.UINodePath;
+import org.alfresco.web.ui.repo.component.UISimpleSearch;
+import org.apache.log4j.Logger;
+import org.apache.log4j.Priority;
+
+/**
+ * Bean providing properties and behaviour for the main folder/document browse screen and
+ * search results screens.
+ *
+ * @author Kevin Roast
+ */
+public class BrowseBean implements IContextListener
+{
+ // ------------------------------------------------------------------------------
+ // Construction
+
+ /**
+ * Default Constructor
+ */
+ public BrowseBean()
+ {
+ UIContextService.getInstance(FacesContext.getCurrentInstance()).registerBean(this);
+
+ initFromClientConfig();
+ }
+
+
+ // ------------------------------------------------------------------------------
+ // Bean property getters and setters
+
+ /**
+ * @param nodeService The NodeService to set.
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * @param searchService The Searcher to set.
+ */
+ public void setSearchService(SearchService searchService)
+ {
+ this.searchService = searchService;
+ }
+
+ /**
+ * @param lockService The Lock Service to set.
+ */
+ public void setLockService(LockService lockService)
+ {
+ this.lockService = lockService;
+ }
+
+ /**
+ * @param navigator The NavigationBean to set.
+ */
+ public void setNavigator(NavigationBean navigator)
+ {
+ this.navigator = navigator;
+ }
+
+ /**
+ * @param dictionaryService The DictionaryService to set.
+ */
+ public void setDictionaryService(DictionaryService dictionaryService)
+ {
+ this.dictionaryService = dictionaryService;
+ }
+
+ /**
+ * @param fileFolderService The FileFolderService to set.
+ */
+ public void setFileFolderService(FileFolderService fileFolderService)
+ {
+ this.fileFolderService = fileFolderService;
+ }
+
+ /**
+ * @return Returns the browse View mode. See UIRichList
+ */
+ public String getBrowseViewMode()
+ {
+ return this.browseViewMode;
+ }
+
+ /**
+ * @param browseViewMode The browse View mode to set. See UIRichList.
+ */
+ public void setBrowseViewMode(String browseViewMode)
+ {
+ this.browseViewMode = browseViewMode;
+ }
+
+ /**
+ * @return Returns true if dashboard view is available for the current node.
+ */
+ public boolean isDashboardView()
+ {
+ return this.dashboardView;
+ }
+
+ /**
+ * @param dashboardView The dashboard view mode to set.
+ */
+ public void setDashboardView(boolean dashboardView)
+ {
+ this.dashboardView = dashboardView;
+ if (dashboardView == true)
+ {
+ FacesContext fc = FacesContext.getCurrentInstance();
+ fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dashboard");
+ }
+ }
+
+ public int getPageSizeContent()
+ {
+ return this.pageSizeContent;
+ }
+
+ public void setPageSizeContent(int pageSizeContent)
+ {
+ this.pageSizeContent = pageSizeContent;
+ this.pageSizeContentStr = Integer.toString(pageSizeContent);
+ }
+
+ public int getPageSizeSpaces()
+ {
+ return this.pageSizeSpaces;
+ }
+
+ public void setPageSizeSpaces(int pageSizeSpaces)
+ {
+ this.pageSizeSpaces = pageSizeSpaces;
+ this.pageSizeSpacesStr = Integer.toString(pageSizeSpaces);
+ }
+
+ public String getPageSizeContentStr()
+ {
+ return this.pageSizeContentStr;
+ }
+
+ public void setPageSizeContentStr(String pageSizeContentStr)
+ {
+ this.pageSizeContentStr = pageSizeContentStr;
+ }
+
+ public String getPageSizeSpacesStr()
+ {
+ return this.pageSizeSpacesStr;
+ }
+
+ public void setPageSizeSpacesStr(String pageSizeSpacesStr)
+ {
+ this.pageSizeSpacesStr = pageSizeSpacesStr;
+ }
+
+ /**
+ * @return Returns the minimum length of a valid search string.
+ */
+ public int getMinimumSearchLength()
+ {
+ return Application.getClientConfig(FacesContext.getCurrentInstance()).
+ getSearchMinimum();
+ }
+
+ /**
+ * @return Returns the panels expanded state map.
+ */
+ public Map getPanels()
+ {
+ return this.panels;
+ }
+
+ /**
+ * @param panels The panels expanded state map.
+ */
+ public void setPanels(Map panels)
+ {
+ this.panels = panels;
+ }
+
+ /**
+ * @return Returns the Space Node being used for the current browse screen action.
+ */
+ public Node getActionSpace()
+ {
+ return this.actionSpace;
+ }
+
+ /**
+ * @param actionSpace Set the Space Node to be used for the current browse screen action.
+ */
+ public void setActionSpace(Node actionSpace)
+ {
+ if (actionSpace != null)
+ {
+ for (NodeEventListener listener : getNodeEventListeners())
+ {
+ listener.created(actionSpace, actionSpace.getType());
+ }
+ }
+ this.actionSpace = actionSpace;
+ }
+
+ /**
+ * @return The document node being used for the current operation
+ */
+ public Node getDocument()
+ {
+ return this.document;
+ }
+
+ /**
+ * @param document The document node to be used for the current operation
+ */
+ public void setDocument(Node document)
+ {
+ if (document != null)
+ {
+ for (NodeEventListener listener : getNodeEventListeners())
+ {
+ listener.created(document, document.getType());
+ }
+ }
+ this.document = document;
+ }
+
+ /**
+ * @param contentRichList The contentRichList to set.
+ */
+ public void setContentRichList(UIRichList browseRichList)
+ {
+ this.contentRichList = browseRichList;
+ if (this.contentRichList != null)
+ {
+ this.contentRichList.setInitialSortColumn(
+ this.viewsConfig.getDefaultSortColumn(PAGE_NAME_BROWSE));
+ this.contentRichList.setInitialSortDescending(
+ this.viewsConfig.hasDescendingSort(PAGE_NAME_BROWSE));
+ }
+ // special case to handle an External Access URL
+ // these URLs restart the JSF lifecycle but an old UIRichList is restored from
+ // the component tree - which needs clearing "late" in the lifecycle process
+ if (externalForceRefresh)
+ {
+ this.contentRichList.setValue(null);
+ externalForceRefresh = false;
+ }
+ }
+
+ /**
+ * @return Returns the contentRichList.
+ */
+ public UIRichList getContentRichList()
+ {
+ return this.contentRichList;
+ }
+
+ /**
+ * @param spacesRichList The spacesRichList to set.
+ */
+ public void setSpacesRichList(UIRichList detailsRichList)
+ {
+ this.spacesRichList = detailsRichList;
+ if (this.spacesRichList != null)
+ {
+ // set the initial sort column and direction
+ this.spacesRichList.setInitialSortColumn(
+ this.viewsConfig.getDefaultSortColumn(PAGE_NAME_BROWSE));
+ this.spacesRichList.setInitialSortDescending(
+ this.viewsConfig.hasDescendingSort(PAGE_NAME_BROWSE));
+ }
+ if (externalForceRefresh)
+ {
+ this.spacesRichList.setValue(null);
+ }
+ }
+
+ /**
+ * @return Returns the spacesRichList.
+ */
+ public UIRichList getSpacesRichList()
+ {
+ return this.spacesRichList;
+ }
+
+ /**
+ * @return Returns the statusMessage component.
+ */
+ public UIStatusMessage getStatusMessage()
+ {
+ return this.statusMessage;
+ }
+
+ /**
+ * @param statusMessage The statusMessage component to set.
+ */
+ public void setStatusMessage(UIStatusMessage statusMessage)
+ {
+ this.statusMessage = statusMessage;
+ }
+
+ /**
+ * @return Returns the deleteMessage.
+ */
+ public String getDeleteMessage()
+ {
+ return this.deleteMessage;
+ }
+
+ /**
+ * @param deleteMessage The deleteMessage to set.
+ */
+ public void setDeleteMessage(String deleteMessage)
+ {
+ this.deleteMessage = deleteMessage;
+ }
+
+ /**
+ * Page accessed bean method to get the container nodes currently being browsed
+ *
+ * @return List of container Node objects for the current browse location
+ */
+ public List getNodes()
+ {
+ // the references to container nodes and content nodes are transient for one use only
+ // we do this so we only query/search once - as we cannot distinguish between node types
+ // until after the query. The logic is a bit confusing but otherwise we would need to
+ // perform the same query or search twice for every screen refresh.
+ if (this.containerNodes == null)
+ {
+ if (this.navigator.getSearchContext() == null)
+ {
+ queryBrowseNodes(this.navigator.getCurrentNodeId());
+ }
+ else
+ {
+ searchBrowseNodes(this.navigator.getSearchContext());
+ }
+ }
+ List result = this.containerNodes;
+
+ // we clear the member variable during invalidateComponents()
+
+ return result;
+ }
+
+ /**
+ * Page accessed bean method to get the content nodes currently being browsed
+ *
+ * @return List of content Node objects for the current browse location
+ */
+ public List getContent()
+ {
+ // see comment in getNodes() above for reasoning here
+ if (this.contentNodes == null)
+ {
+ if (this.navigator.getSearchContext() == null)
+ {
+ queryBrowseNodes(this.navigator.getCurrentNodeId());
+ }
+ else
+ {
+ searchBrowseNodes(this.navigator.getSearchContext());
+ }
+ }
+ List result = this.contentNodes;
+
+ // we clear the member variable during invalidateComponents()
+
+ return result;
+ }
+
+ /**
+ * Setup the common properties required at data-binding time.
+ *
+ * These are properties used by components on the page when iterating over the nodes.
+ * The properties are available as the Node is a Map so they can be accessed directly
+ * by name. Information such as download URL, size and filetype are provided etc.
+ *
+ * We use a set of anonymous inner classes to provide the implemention for the property
+ * getters. The interfaces are only called when the properties are first requested.
+ *
+ * @param node Node to add the properties too
+ */
+ public void setupCommonBindingProperties(Node node)
+ {
+ // special properties to be used by the value binding components on the page
+ node.addPropertyResolver("url", this.resolverUrl);
+ node.addPropertyResolver("webdavUrl", this.resolverWebdavUrl);
+ node.addPropertyResolver("cifsPath", this.resolverCifsPath);
+ node.addPropertyResolver("fileType16", this.resolverFileType16);
+ node.addPropertyResolver("fileType32", this.resolverFileType32);
+ node.addPropertyResolver("size", this.resolverSize);
+ }
+
+
+ // ------------------------------------------------------------------------------
+ // IContextListener implementation
+
+ /**
+ * @see org.alfresco.web.app.context.IContextListener#contextUpdated()
+ */
+ public void contextUpdated()
+ {
+ invalidateComponents();
+ }
+
+
+ // ------------------------------------------------------------------------------
+ // NodeEventListener listeners
+
+ /**
+ * Add a listener to those called by the BrowseBean when nodes are created
+ */
+ public void addNodeEventListener(NodeEventListener listener)
+ {
+ getNodeEventListeners().add(listener);
+ }
+
+ /**
+ * Remove a listener from the list of those called by BrowseBean
+ */
+ public void removeNodeEventListener(NodeEventListener listener)
+ {
+ getNodeEventListeners().remove(listener);
+ }
+
+
+ // ------------------------------------------------------------------------------
+ // Navigation action event handlers
+
+ /**
+ * Change the current view mode based on user selection
+ *
+ * @param event ActionEvent
+ */
+ public void viewModeChanged(ActionEvent event)
+ {
+ UIModeList viewList = (UIModeList)event.getComponent();
+
+ // get the view mode ID
+ String viewMode = viewList.getValue().toString();
+
+ if (VIEWMODE_DASHBOARD.equals(viewMode) == false)
+ {
+ // set the page size based on the style of display
+ int pageSize = this.viewsConfig.getDefaultPageSize(PAGE_NAME_BROWSE, viewMode);
+ setPageSizeContent(pageSize);
+ setPageSizeSpaces(pageSize);
+
+ if (logger.isDebugEnabled())
+ logger.debug("Browse view page size set to: " + pageSize);
+
+ setDashboardView(false);
+
+ // push the view mode into the lists
+ setBrowseViewMode(viewMode);
+
+ navigateBrowseScreen();
+ }
+ else
+ {
+ // special case for Dashboard view
+ setDashboardView(true);
+ }
+ }
+
+
+ // ------------------------------------------------------------------------------
+ // Helper methods
+
+ /**
+ * Query a list of nodes for the specified parent node Id
+ *
+ * @param parentNodeId Id of the parent node or null for the root node
+ */
+ private void queryBrowseNodes(String parentNodeId)
+ {
+ long startTime = 0;
+ if (logger.isDebugEnabled())
+ startTime = System.currentTimeMillis();
+
+ UserTransaction tx = null;
+ try
+ {
+ FacesContext context = FacesContext.getCurrentInstance();
+ tx = Repository.getUserTransaction(context, true);
+ tx.begin();
+
+ NodeRef parentRef;
+ if (parentNodeId == null)
+ {
+ // no specific parent node specified - use the root node
+ parentRef = this.nodeService.getRootNode(Repository.getStoreRef());
+ }
+ else
+ {
+ // build a NodeRef for the specified Id and our store
+ parentRef = new NodeRef(Repository.getStoreRef(), parentNodeId);
+ }
+
+ List childRefs = this.nodeService.getChildAssocs(parentRef,
+ ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
+ this.containerNodes = new ArrayList(childRefs.size());
+ this.contentNodes = new ArrayList(childRefs.size());
+ for (ChildAssociationRef ref: childRefs)
+ {
+ // create our Node representation from the NodeRef
+ NodeRef nodeRef = ref.getChildRef();
+
+ if (this.nodeService.exists(nodeRef))
+ {
+ // find it's type so we can see if it's a node we are interested in
+ QName type = this.nodeService.getType(nodeRef);
+
+ // make sure the type is defined in the data dictionary
+ TypeDefinition typeDef = this.dictionaryService.getType(type);
+
+ if (typeDef != null)
+ {
+ MapNode node = null;
+
+ // look for Space folder node
+ if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_FOLDER) == true &&
+ this.dictionaryService.isSubClass(type, ContentModel.TYPE_SYSTEM_FOLDER) == false)
+ {
+ // create our Node representation
+ node = new MapNode(nodeRef, this.nodeService, true);
+ node.addPropertyResolver("icon", this.resolverSpaceIcon);
+ node.addPropertyResolver("smallIcon", this.resolverSmallIcon);
+
+ this.containerNodes.add(node);
+ }
+ // look for File content node
+ else if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT))
+ {
+ // create our Node representation
+ node = new MapNode(nodeRef, this.nodeService, true);
+ setupCommonBindingProperties(node);
+
+ this.contentNodes.add(node);
+ }
+ // look for File Link object node
+ else if (ContentModel.TYPE_FILELINK.equals(type))
+ {
+ // create our File Link Node representation
+ node = new MapNode(nodeRef, this.nodeService, true);
+ node.addPropertyResolver("url", this.resolverLinkUrl);
+ node.addPropertyResolver("webdavUrl", this.resolverLinkWebdavUrl);
+ node.addPropertyResolver("cifsPath", this.resolverLinkCifsPath);
+ node.addPropertyResolver("fileType16", this.resolverFileType16);
+ node.addPropertyResolver("fileType32", this.resolverFileType32);
+ node.addPropertyResolver("size", this.resolverSize);
+
+ this.contentNodes.add(node);
+ }
+ else if (ContentModel.TYPE_FOLDERLINK.equals(type))
+ {
+ // create our Folder Link Node representation
+ node = new MapNode(nodeRef, this.nodeService, true);
+ node.addPropertyResolver("icon", this.resolverSpaceIcon);
+ node.addPropertyResolver("smallIcon", this.resolverSmallIcon);
+
+ this.containerNodes.add(node);
+ }
+
+ // inform any listeners that a Node wrapper has been created
+ if (node != null)
+ {
+ for (NodeEventListener listener : getNodeEventListeners())
+ {
+ listener.created(node, type);
+ }
+ }
+ }
+ else
+ {
+ if (logger.isEnabledFor(Priority.WARN))
+ logger.warn("Found invalid object in database: id = " + nodeRef + ", type = " + type);
+ }
+ }
+ }
+
+ // commit the transaction
+ tx.commit();
+ }
+ catch (InvalidNodeRefException refErr)
+ {
+ Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
+ FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {refErr.getNodeRef()}) );
+ this.containerNodes = Collections.emptyList();
+ this.contentNodes = Collections.emptyList();
+ try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
+ }
+ catch (Throwable err)
+ {
+ Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
+ FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
+ this.containerNodes = Collections.emptyList();
+ this.contentNodes = Collections.emptyList();
+ try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
+ }
+
+ if (logger.isDebugEnabled())
+ {
+ long endTime = System.currentTimeMillis();
+ logger.debug("Time to query and build map nodes: " + (endTime - startTime) + "ms");
+ }
+ }
+
+ /**
+ * Search for a list of nodes using the specific search context
+ *
+ * @param searchContext To use to perform the search
+ */
+ private void searchBrowseNodes(SearchContext searchContext)
+ {
+ long startTime = 0;
+ if (logger.isDebugEnabled())
+ startTime = System.currentTimeMillis();
+
+ // get the searcher object to build the query
+ String query = searchContext.buildQuery(getMinimumSearchLength());
+ if (query == null)
+ {
+ // failed to build a valid query, the user probably did not enter the
+ // minimum text required to construct a valid search
+ Utils.addErrorMessage(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), MSG_SEARCH_MINIMUM),
+ new Object[] {getMinimumSearchLength()}));
+ this.containerNodes = Collections.emptyList();
+ this.contentNodes = Collections.emptyList();
+ return;
+ }
+
+ // perform the search against the repo
+ UserTransaction tx = null;
+ ResultSet results = null;
+ try
+ {
+ tx = Repository.getUserTransaction(FacesContext.getCurrentInstance(), true);
+ tx.begin();
+
+ // Limit search to the first 100 matches
+ SearchParameters sp = new SearchParameters();
+ sp.setLanguage(SearchService.LANGUAGE_LUCENE);
+ sp.setQuery(query);
+ sp.addStore(Repository.getStoreRef());
+
+ int searchLimit = Application.getClientConfig(FacesContext.getCurrentInstance()).getSearchMaxResults();
+ if(searchLimit > 0)
+ {
+ sp.setLimitBy(LimitBy.FINAL_SIZE);
+ sp.setLimit(searchLimit);
+ }
+
+ results = this.searchService.query(sp);
+ if (logger.isDebugEnabled())
+ logger.debug("Search results returned: " + results.length());
+
+ // create a list of items from the results
+ this.containerNodes = new ArrayList(results.length());
+ this.contentNodes = new ArrayList(results.length());
+ if (results.length() != 0)
+ {
+ for (ResultSetRow row: results)
+ {
+ NodeRef nodeRef = row.getNodeRef();
+
+ if (this.nodeService.exists(nodeRef))
+ {
+ // find it's type so we can see if it's a node we are interested in
+ QName type = this.nodeService.getType(nodeRef);
+
+ // make sure the type is defined in the data dictionary
+ TypeDefinition typeDef = this.dictionaryService.getType(type);
+
+ if (typeDef != null)
+ {
+ MapNode node = null;
+
+ // look for Space or File nodes
+ if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_FOLDER) &&
+ this.dictionaryService.isSubClass(type, ContentModel.TYPE_SYSTEM_FOLDER) == false)
+ {
+ // create our Node representation
+ node = new MapNode(nodeRef, this.nodeService, false);
+
+ node.addPropertyResolver("path", this.resolverPath);
+ node.addPropertyResolver("displayPath", this.resolverDisplayPath);
+ node.addPropertyResolver("icon", this.resolverSpaceIcon);
+ node.addPropertyResolver("smallIcon", this.resolverSmallIcon);
+
+ this.containerNodes.add(node);
+ }
+ else if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT))
+ {
+ // create our Node representation
+ node = new MapNode(nodeRef, this.nodeService, false);
+
+ setupCommonBindingProperties(node);
+
+ node.addPropertyResolver("path", this.resolverPath);
+ node.addPropertyResolver("displayPath", this.resolverDisplayPath);
+
+ this.contentNodes.add(node);
+ }
+ // look for File Link object node
+ else if (ContentModel.TYPE_FILELINK.equals(type))
+ {
+ // create our File Link Node representation
+ node = new MapNode(nodeRef, this.nodeService, false);
+ node.addPropertyResolver("url", this.resolverLinkUrl);
+ node.addPropertyResolver("webdavUrl", this.resolverLinkWebdavUrl);
+ node.addPropertyResolver("cifsPath", this.resolverLinkCifsPath);
+ node.addPropertyResolver("fileType16", this.resolverFileType16);
+ node.addPropertyResolver("fileType32", this.resolverFileType32);
+ node.addPropertyResolver("size", this.resolverSize);
+ node.addPropertyResolver("path", this.resolverPath);
+ node.addPropertyResolver("displayPath", this.resolverDisplayPath);
+
+ this.contentNodes.add(node);
+ }
+ else if (ContentModel.TYPE_FOLDERLINK.equals(type))
+ {
+ // create our Folder Link Node representation
+ node = new MapNode(nodeRef, this.nodeService, false);
+ node.addPropertyResolver("icon", this.resolverSpaceIcon);
+ node.addPropertyResolver("smallIcon", this.resolverSmallIcon);
+ node.addPropertyResolver("path", this.resolverPath);
+ node.addPropertyResolver("displayPath", this.resolverDisplayPath);
+
+ this.containerNodes.add(node);
+ }
+
+ // inform any listeners that a Node wrapper has been created
+ if (node != null)
+ {
+ for (NodeEventListener listener : getNodeEventListeners())
+ {
+ listener.created(node, type);
+ }
+ }
+ }
+ else
+ {
+ if (logger.isEnabledFor(Priority.WARN))
+ logger.warn("Found invalid object in database: id = " + nodeRef + ", type = " + type);
+ }
+ }
+ else
+ {
+ if (logger.isEnabledFor(Priority.WARN))
+ logger.warn("Missing object returned from search indexes: id = " + nodeRef + " search query: " + query);
+ }
+ }
+ }
+
+ // commit the transaction
+ tx.commit();
+ }
+ catch (InvalidNodeRefException refErr)
+ {
+ Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
+ FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {refErr.getNodeRef()}) );
+ this.containerNodes = Collections.emptyList();
+ this.contentNodes = Collections.emptyList();
+ try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
+ }
+ catch (Throwable err)
+ {
+ logger.info("Search failed for: " + query);
+ Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
+ FacesContext.getCurrentInstance(), Repository.ERROR_SEARCH), new Object[] {err.getMessage()}), err );
+ this.containerNodes = Collections.emptyList();
+ this.contentNodes = Collections.emptyList();
+ try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
+ }
+ finally
+ {
+ if (results != null)
+ {
+ results.close();
+ }
+ }
+
+ if (logger.isDebugEnabled())
+ {
+ long endTime = System.currentTimeMillis();
+ logger.debug("Time to query and build map nodes: " + (endTime - startTime) + "ms");
+ }
+ }
+
+
+ // ------------------------------------------------------------------------------
+ // Property Resolvers
+
+ public NodePropertyResolver resolverDownload = new NodePropertyResolver() {
+ public Object get(Node node) {
+ return DownloadContentServlet.generateDownloadURL(node.getNodeRef(), node.getName());
+ }
+ };
+
+ public NodePropertyResolver resolverUrl = new NodePropertyResolver() {
+ public Object get(Node node) {
+ return DownloadContentServlet.generateBrowserURL(node.getNodeRef(), node.getName());
+ }
+ };
+
+ public NodePropertyResolver resolverWebdavUrl = new NodePropertyResolver() {
+ public Object get(Node node) {
+ return Utils.generateURL(FacesContext.getCurrentInstance(), node, URLMode.WEBDAV);
+ }
+ };
+
+ public NodePropertyResolver resolverCifsPath = new NodePropertyResolver() {
+ public Object get(Node node) {
+ return Utils.generateURL(FacesContext.getCurrentInstance(), node, URLMode.CIFS);
+ }
+ };
+
+ public NodePropertyResolver resolverLinkDownload = new NodePropertyResolver() {
+ public Object get(Node node) {
+ NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION);
+ if (nodeService.exists(destRef) == true)
+ {
+ String destName = Repository.getNameForNode(nodeService, destRef);
+ return DownloadContentServlet.generateDownloadURL(node.getNodeRef(), destName);
+ }
+ else
+ {
+ // TODO: link object is missing - navigate to a page with appropriate message
+ return "#";
+ }
+ }
+ };
+
+ public NodePropertyResolver resolverLinkUrl = new NodePropertyResolver() {
+ public Object get(Node node) {
+ NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION);
+ if (nodeService.exists(destRef) == true)
+ {
+ String destName = Repository.getNameForNode(nodeService, destRef);
+ return DownloadContentServlet.generateBrowserURL(destRef, destName);
+ }
+ else
+ {
+ // TODO: link object is missing - navigate to a page with appropriate message
+ return "#";
+ }
+ }
+ };
+
+ public NodePropertyResolver resolverLinkWebdavUrl = new NodePropertyResolver() {
+ public Object get(Node node) {
+ NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION);
+ if (nodeService.exists(destRef) == true)
+ {
+ return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.WEBDAV);
+ }
+ else
+ {
+ // TODO: link object is missing - navigate to a page with appropriate message
+ return "#";
+ }
+ }
+ };
+
+ public NodePropertyResolver resolverLinkCifsPath = new NodePropertyResolver() {
+ public Object get(Node node) {
+ NodeRef destRef = (NodeRef)node.getProperties().get(ContentModel.PROP_LINK_DESTINATION);
+ if (nodeService.exists(destRef) == true)
+ {
+ return Utils.generateURL(FacesContext.getCurrentInstance(), new Node(destRef), URLMode.CIFS);
+ }
+ else
+ {
+ // TODO: link object is missing - navigate to a page with appropriate message
+ return "#";
+ }
+ }
+ };
+
+ public NodePropertyResolver resolverFileType16 = new NodePropertyResolver() {
+ public Object get(Node node) {
+ return Utils.getFileTypeImage(node.getName(), true);
+ }
+ };
+
+ public NodePropertyResolver resolverFileType32 = new NodePropertyResolver() {
+ public Object get(Node node) {
+ return Utils.getFileTypeImage(node.getName(), false);
+ }
+ };
+
+ public NodePropertyResolver resolverPath = new NodePropertyResolver() {
+ public Object get(Node node) {
+ return nodeService.getPath(node.getNodeRef());
+ }
+ };
+
+ public NodePropertyResolver resolverDisplayPath = new NodePropertyResolver() {
+ public Object get(Node node) {
+ // TODO: replace this with a method that shows the full display name - not QNames?
+ return Repository.getDisplayPath( (Path)node.getProperties().get("path") );
+ }
+ };
+
+ public NodePropertyResolver resolverSpaceIcon = new NodePropertyResolver() {
+ public Object get(Node node) {
+ QNameNodeMap props = (QNameNodeMap)node.getProperties();
+ String icon = (String)props.getRaw("app:icon");
+ return (icon != null ? icon : CreateSpaceWizard.DEFAULT_SPACE_ICON_NAME);
+ }
+ };
+
+ public NodePropertyResolver resolverSmallIcon = new NodePropertyResolver() {
+ public Object get(Node node) {
+ QNameNodeMap props = (QNameNodeMap)node.getProperties();
+ String icon = (String)props.getRaw("app:icon");
+ return (icon != null ? icon + "-16" : SPACE_SMALL_DEFAULT);
+ }
+ };
+
+ public NodePropertyResolver resolverMimetype = new NodePropertyResolver() {
+ public Object get(Node node) {
+ ContentData content = (ContentData)node.getProperties().get(ContentModel.PROP_CONTENT);
+ return (content != null ? content.getMimetype() : null);
+ }
+ };
+
+ public NodePropertyResolver resolverSize = new NodePropertyResolver() {
+ public Object get(Node node) {
+ ContentData content = (ContentData)node.getProperties().get(ContentModel.PROP_CONTENT);
+ return (content != null ? new Long(content.getSize()) : 0L);
+ }
+ };
+
+
+ // ------------------------------------------------------------------------------
+ // Navigation action event handlers
+
+ /**
+ * Action called from the Simple Search component.
+ * Sets up the SearchContext object with the values from the simple search menu.
+ */
+ public void search(ActionEvent event)
+ {
+ // setup the search text string on the top-level navigation handler
+ UISimpleSearch search = (UISimpleSearch)event.getComponent();
+ this.navigator.setSearchContext(search.getSearchContext());
+
+ navigateBrowseScreen();
+ }
+
+ /**
+ * Action called to Close the search dialog by returning to the last view node Id
+ */
+ public void closeSearch(ActionEvent event)
+ {
+ // set the current node Id ready for page refresh
+ this.navigator.setCurrentNodeId( this.navigator.getCurrentNodeId() );
+ }
+
+ /**
+ * Update page size based on user selection
+ */
+ public void updateSpacesPageSize(ActionEvent event)
+ {
+ try
+ {
+ int size = Integer.parseInt(this.pageSizeSpacesStr);
+ if (size >= 0)
+ {
+ this.pageSizeSpaces = size;
+ }
+ else
+ {
+ // reset to known value if this occurs
+ this.pageSizeSpacesStr = Integer.toString(this.pageSizeSpaces);
+ }
+ }
+ catch (NumberFormatException err)
+ {
+ // reset to known value if this occurs
+ this.pageSizeSpacesStr = Integer.toString(this.pageSizeSpaces);
+ }
+ }
+
+ /**
+ * Update page size based on user selection
+ */
+ public void updateContentPageSize(ActionEvent event)
+ {
+ try
+ {
+ int size = Integer.parseInt(this.pageSizeContentStr);
+ if (size >= 0)
+ {
+ this.pageSizeContent = size;
+ }
+ else
+ {
+ // reset to known value if this occurs
+ this.pageSizeContentStr = Integer.toString(this.pageSizeContent);
+ }
+ }
+ catch (NumberFormatException err)
+ {
+ // reset to known value if this occurs
+ this.pageSizeContentStr = Integer.toString(this.pageSizeContent);
+ }
+ }
+
+ /**
+ * Action called when a folder space is clicked.
+ * Navigate into the space.
+ */
+ public void clickSpace(ActionEvent event)
+ {
+ UIActionLink link = (UIActionLink)event.getComponent();
+ Map params = link.getParameterMap();
+ String id = params.get("id");
+ if (id != null && id.length() != 0)
+ {
+ try
+ {
+ NodeRef ref = new NodeRef(Repository.getStoreRef(), id);
+
+ // handle special folder link node case
+ if (ContentModel.TYPE_FOLDERLINK.equals(this.nodeService.getType(ref)))
+ {
+ ref = (NodeRef)this.nodeService.getProperty(ref, ContentModel.PROP_LINK_DESTINATION);
+ }
+
+ clickSpace(ref);
+ }
+ catch (InvalidNodeRefException refErr)
+ {
+ Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
+ FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {id}) );
+ }
+ }
+ }
+
+ /**
+ * Action called when a folder space is clicked.
+ *
+ * @param nodeRef The node being clicked
+ */
+ public void clickSpace(NodeRef nodeRef)
+ {
+ // refresh UI based on node selection
+ updateUILocation(nodeRef);
+ }
+
+ /**
+ * Handler called when a path element is clicked - navigate to the appropriate Space
+ */
+ public void clickSpacePath(ActionEvent event)
+ {
+ UINodePath.PathElementEvent pathEvent = (UINodePath.PathElementEvent)event;
+ NodeRef ref = pathEvent.NodeReference;
+ try
+ {
+ // refresh UI based on node selection
+ this.updateUILocation(ref);
+ }
+ catch (InvalidNodeRefException refErr)
+ {
+ Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
+ FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {ref.getId()}) );
+ }
+ }
+
+ /**
+ * Action called when a folders direct descendant (in the 'list' browse mode) is clicked.
+ * Navigate into the the descendant space.
+ */
+ public void clickDescendantSpace(ActionEvent event)
+ {
+ UINodeDescendants.NodeSelectedEvent nodeEvent = (UINodeDescendants.NodeSelectedEvent)event;
+ NodeRef nodeRef = nodeEvent.NodeReference;
+ if (nodeRef == null)
+ {
+ throw new IllegalStateException("NodeRef returned from UINodeDescendants.NodeSelectedEvent cannot be null!");
+ }
+
+ if (logger.isDebugEnabled())
+ logger.debug("Selected noderef Id: " + nodeRef.getId());
+
+ try
+ {
+ // user can either select a descendant of a node display on the page which means we
+ // must add the it's parent and itself to the breadcrumb
+ ChildAssociationRef parentAssocRef = nodeService.getPrimaryParent(nodeRef);
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Selected item getPrimaryParent().getChildRef() noderef Id: " + parentAssocRef.getChildRef().getId());
+ logger.debug("Selected item getPrimaryParent().getParentRef() noderef Id: " + parentAssocRef.getParentRef().getId());
+ logger.debug("Current value getNavigator().getCurrentNodeId() noderef Id: " + this.navigator.getCurrentNodeId());
+ }
+
+ if (nodeEvent.IsParent == false)
+ {
+ // a descendant of the displayed node was selected
+ // first refresh based on the parent and add to the breadcrumb
+ updateUILocation(parentAssocRef.getParentRef());
+
+ // now add our selected node
+ updateUILocation(nodeRef);
+ }
+ else
+ {
+ // else the parent ellipses i.e. the displayed node was selected
+ updateUILocation(nodeRef);
+ }
+ }
+ catch (InvalidNodeRefException refErr)
+ {
+ Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
+ FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {nodeRef.getId()}) );
+ }
+ }
+
+ /**
+ * Action event called by all Browse actions that need to setup a Space context
+ * before an action page/wizard is called. The context will be a Node in setActionSpace() which
+ * can be retrieved on the action page from BrowseBean.getActionSpace().
+ *
+ * @param event ActionEvent
+ */
+ public void setupSpaceAction(ActionEvent event)
+ {
+ UIActionLink link = (UIActionLink)event.getComponent();
+ Map params = link.getParameterMap();
+ String id = params.get("id");
+ setupSpaceAction(id, true);
+ }
+
+ /**
+ * Public helper to setup action pages with Space context
+ *
+ * @param id of the Space node to setup context for
+ */
+ public void setupSpaceAction(String id, boolean invalidate)
+ {
+ if (id != null && id.length() != 0)
+ {
+ if (logger.isDebugEnabled())
+ logger.debug("Setup for action, setting current space to: " + id);
+
+ try
+ {
+ // create the node ref, then our node representation
+ NodeRef ref = new NodeRef(Repository.getStoreRef(), id);
+ Node node = new Node(ref);
+
+ // resolve icon in-case one has not been set
+ node.addPropertyResolver("icon", this.resolverSpaceIcon);
+
+ // prepare a node for the action context
+ setActionSpace(node);
+
+ // setup the dispatch context in case it is required
+ this.navigator.setupDispatchContext(node);
+ }
+ catch (InvalidNodeRefException refErr)
+ {
+ Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
+ FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {id}) );
+ }
+ }
+ else
+ {
+ setActionSpace(null);
+ }
+
+ // clear the UI state in preparation for finishing the next action
+ if (invalidate == true)
+ {
+ // use the context service to notify all registered beans
+ UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans();
+ }
+ }
+
+ /**
+ * Acrtion event called by Delete Space actions. We setup the action space as normal, then prepare
+ * any special case message string to be shown to the user if they are trying to delete specific spaces.
+ */
+ public void setupDeleteAction(ActionEvent event)
+ {
+ String message = null;
+
+ setupSpaceAction(event);
+
+ Node node = getActionSpace();
+ if (node != null)
+ {
+ NodeRef companyRootRef = new NodeRef(Repository.getStoreRef(), Application.getCompanyRootId());
+ if (node.getNodeRef().equals(companyRootRef))
+ {
+ message = Application.getMessage(FacesContext.getCurrentInstance(), MSG_DELETE_COMPANYROOT);
+ }
+ }
+
+ setDeleteMessage(message);
+ }
+
+ /**
+ * Action event called by all actions that need to setup a Content Document context on the
+ * BrowseBean before an action page/wizard is called. The context will be a Node in
+ * setDocument() which can be retrieved on the action page from BrowseBean.getDocument().
+ */
+ public void setupContentAction(ActionEvent event)
+ {
+ UIActionLink link = (UIActionLink)event.getComponent();
+ Map params = link.getParameterMap();
+ setupContentAction(params.get("id"), true);
+ }
+
+ /**
+ * Public helper to setup action pages with content context
+ *
+ * @param id of the content node to setup context for
+ */
+ public void setupContentAction(String id, boolean invalidate)
+ {
+ if (id != null && id.length() != 0)
+ {
+ if (logger.isDebugEnabled())
+ logger.debug("Setup for action, setting current document to: " + id);
+
+ try
+ {
+ // create the node ref, then our node representation
+ NodeRef ref = new NodeRef(Repository.getStoreRef(), id);
+ Node node = new Node(ref);
+
+ // store the URL to for downloading the content
+ if (ContentModel.TYPE_FILELINK.equals(node.getType()))
+ {
+ node.addPropertyResolver("url", this.resolverLinkDownload);
+ }
+ else
+ {
+ node.addPropertyResolver("url", this.resolverDownload);
+ }
+ node.addPropertyResolver("fileType32", this.resolverFileType32);
+ node.addPropertyResolver("mimetype", this.resolverMimetype);
+ node.addPropertyResolver("size", this.resolverSize);
+
+ for (NodeEventListener listener : getNodeEventListeners())
+ {
+ listener.created(node, node.getType());
+ }
+
+ // get hold of the DocumentDetailsBean and reset it
+ DocumentDetailsBean docDetails = (DocumentDetailsBean)FacesContext.getCurrentInstance().
+ getExternalContext().getSessionMap().get("DocumentDetailsBean");
+ if (docDetails != null)
+ {
+ docDetails.reset();
+ }
+
+ // remember the document
+ setDocument(node);
+
+ // setup the dispatch context in case it is required
+ this.navigator.setupDispatchContext(node);
+ }
+ catch (InvalidNodeRefException refErr)
+ {
+ Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
+ FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {id}) );
+ }
+ }
+ else
+ {
+ setDocument(null);
+ }
+
+ // clear the UI state in preparation for finishing the next action
+ if (invalidate == true)
+ {
+ // use the context service to notify all registered beans
+ UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans();
+ }
+ }
+
+ /**
+ * Removes the given node from the breadcrumb i.e. following a delete
+ *
+ * @param node The space to remove from the breadcrumb
+ */
+ public void removeSpaceFromBreadcrumb(Node node)
+ {
+ List location = navigator.getLocation();
+ IBreadcrumbHandler handler = location.get(location.size() - 1);
+ if (handler instanceof BrowseBreadcrumbHandler)
+ {
+ // see if the current breadcrumb location is our node
+ if ( ((BrowseBreadcrumbHandler)handler).getNodeRef().equals(node.getNodeRef()) == true )
+ {
+ location.remove(location.size() - 1);
+
+ // now work out which node to set the list to refresh against
+ if (location.size() != 0)
+ {
+ handler = location.get(location.size() - 1);
+ if (handler instanceof BrowseBreadcrumbHandler)
+ {
+ // change the current node Id
+ navigator.setCurrentNodeId(((BrowseBreadcrumbHandler)handler).getNodeRef().getId());
+ }
+ else
+ {
+ // TODO: shouldn't do this - but for now the user home dir is the root!
+ navigator.setCurrentNodeId(Application.getCurrentUser(FacesContext.getCurrentInstance()).getHomeSpaceId());
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Support for refresh of lists via special case for an External Access URL.
+ * these URLs restart the JSF lifecycle but an old UIRichList is restored from
+ * the component tree - which needs clearing "late" in the lifecycle process.
+ */
+ public void externalAccessRefresh()
+ {
+ this.externalForceRefresh = true;
+ }
+
+ /**
+ * Save the state of the panel that was expanded/collapsed
+ */
+ public void expandPanel(ActionEvent event)
+ {
+ if (event instanceof ExpandedEvent)
+ {
+ String id = event.getComponent().getId();
+ this.panels.put(id, ((ExpandedEvent)event).State);
+ }
+ }
+
+
+ // ------------------------------------------------------------------------------
+ // Private helpers
+
+ /**
+ * Initialise default values from client configuration
+ */
+ private void initFromClientConfig()
+ {
+ ConfigService config = Application.getConfigService(FacesContext.getCurrentInstance());
+
+ this.viewsConfig = (ViewsConfigElement)config.getConfig("Views").
+ getConfigElement(ViewsConfigElement.CONFIG_ELEMENT_ID);
+
+ this.browseViewMode = this.viewsConfig.getDefaultView(PAGE_NAME_BROWSE);
+ int pageSize = this.viewsConfig.getDefaultPageSize(PAGE_NAME_BROWSE, this.browseViewMode);
+ setPageSizeContent(pageSize);
+ setPageSizeSpaces(pageSize);
+ }
+
+ /**
+ * @return the Set of NodeEventListeners registered against this bean
+ */
+ private Set getNodeEventListeners()
+ {
+ if (this.nodeEventListeners == null)
+ {
+ this.nodeEventListeners = new HashSet();
+
+ FacesContext fc = FacesContext.getCurrentInstance();
+
+ Config listenerConfig = Application.getConfigService(fc).getConfig("Node Event Listeners");
+ if (listenerConfig != null)
+ {
+ ConfigElement listenerElement = listenerConfig.getConfigElement("node-event-listeners");
+ if (listenerElement != null)
+ {
+ for (ConfigElement child : listenerElement.getChildren())
+ {
+ if (child.getName().equals("listener"))
+ {
+ // retrieved the JSF Managed Bean identified in the config
+ String listenerName = child.getValue().trim();
+ Object bean = FacesHelper.getManagedBean(fc, listenerName);
+ if (bean instanceof NodeEventListener)
+ {
+ addNodeEventListener((NodeEventListener)bean);
+ }
+ }
+ }
+ }
+ }
+ }
+ return this.nodeEventListeners;
+ }
+
+ /**
+ * Refresh the UI after a Space selection change. Adds the selected space to the breadcrumb
+ * location path and also updates the list components in the UI.
+ *
+ * @param ref NodeRef of the selected space
+ */
+ public void updateUILocation(NodeRef ref)
+ {
+ // get the current breadcrumb location and append a new handler to it
+ // our handler know the ID of the selected node and the display label for it
+ List location = this.navigator.getLocation();
+ if (location.size() != 0)
+ {
+ // attempt to find the ID - if it's already in the breadcrumb then we
+ // navigate directly to that node - rather than add duplication to the breadcrumb path
+ boolean foundNode = false;
+ for (int i=0; i newLocation = new ArrayList(i+1);
+ //newLocation.addAll(location.subList(0, i + 1));
+ //this.navigator.setLocation(newLocation);
+ // TODO: but instead for now we do this:
+ int count = location.size();
+ for (int n=i+1; n nodeEventListeners = null;
+
+ /** Collapsable Panel state */
+ private Map panels = new HashMap(4, 1.0f);
+
+ /** Component references */
+ protected UIRichList spacesRichList;
+ protected UIRichList contentRichList;
+ private UIStatusMessage statusMessage;
+
+ /** Transient lists of container and content nodes for display */
+ protected List containerNodes = null;
+ protected List contentNodes = null;
+
+ /** The current space and it's properties - if any */
+ protected Node actionSpace;
+
+ /** The current document */
+ protected Node document;
+
+ /** Special message to display when user deleting certain folders e.g. Company Home */
+ private String deleteMessage;
+
+ /** The current browse view mode - set to a well known IRichListRenderer identifier */
+ private String browseViewMode;
+
+ /** The current browse view page sizes */
+ private int pageSizeSpaces;
+ private int pageSizeContent;
+ private String pageSizeSpacesStr;
+ private String pageSizeContentStr;
+
+ /** True if current space has a dashboard (template) view available */
+ private boolean dashboardView;
+
+ private boolean externalForceRefresh = false;
+}
diff --git a/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java b/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java
index 365bc43134..4f0c938ad5 100644
--- a/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java
+++ b/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java
@@ -1,988 +1,986 @@
-/*
- * Copyright (C) 2005 Alfresco, Inc.
- *
- * Licensed under the Mozilla Public License version 1.1
- * with a permitted attribution clause. You may obtain a
- * copy of the License at
- *
- * http://www.alfresco.org/legal/license.txt
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the
- * License.
- */
-package org.alfresco.web.bean;
-
-import java.io.File;
-import java.io.Serializable;
-import java.text.MessageFormat;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.faces.context.FacesContext;
-import javax.faces.event.ActionEvent;
-import javax.transaction.UserTransaction;
-
-import org.alfresco.model.ContentModel;
-import org.alfresco.repo.content.MimetypeMap;
-import org.alfresco.repo.version.VersionModel;
-import org.alfresco.service.cmr.coci.CheckOutCheckInService;
-import org.alfresco.service.cmr.repository.ChildAssociationRef;
-import org.alfresco.service.cmr.repository.ContentData;
-import org.alfresco.service.cmr.repository.ContentReader;
-import org.alfresco.service.cmr.repository.ContentService;
-import org.alfresco.service.cmr.repository.ContentWriter;
-import org.alfresco.service.cmr.repository.InvalidNodeRefException;
-import org.alfresco.service.cmr.repository.NodeRef;
-import org.alfresco.service.cmr.repository.NodeService;
-import org.alfresco.service.cmr.version.Version;
-import org.alfresco.service.cmr.version.VersionType;
-import org.alfresco.web.app.AlfrescoNavigationHandler;
-import org.alfresco.web.app.Application;
-import org.alfresco.web.app.context.UIContextService;
-import org.alfresco.web.app.servlet.DownloadContentServlet;
-import org.alfresco.web.bean.repository.Node;
-import org.alfresco.web.bean.repository.Repository;
-import org.alfresco.web.templating.OutputUtil;
-import org.alfresco.web.templating.TemplatingService;
-import org.alfresco.web.ui.common.Utils;
-import org.alfresco.web.ui.common.component.UIActionLink;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * @author Kevin Roast
- */
-public class CheckinCheckoutBean
-{
- // ------------------------------------------------------------------------------
- // Bean property getters and setters
-
- /**
- * @param navigator The NavigationBean to set.
- */
- public void setNavigator(NavigationBean navigator)
- {
- this.navigator = navigator;
- }
-
- /**
- * @return Returns the BrowseBean.
- */
- public BrowseBean getBrowseBean()
- {
- return this.browseBean;
- }
-
- /**
- * @param browseBean The BrowseBean to set.
- */
- public void setBrowseBean(BrowseBean browseBean)
- {
- this.browseBean = browseBean;
- }
-
- /**
- * @return Returns the NodeService.
- */
- public NodeService getNodeService()
- {
- return this.nodeService;
- }
-
- /**
- * @param nodeService The NodeService to set.
- */
- public void setNodeService(NodeService nodeService)
- {
- this.nodeService = nodeService;
- }
-
- /**
- * @return Returns the VersionOperationsService.
- */
- public CheckOutCheckInService getVersionOperationsService()
- {
- return this.versionOperationsService;
- }
-
- /**
- * @param versionOperationsService The VersionOperationsService to set.
- */
- public void setVersionOperationsService(CheckOutCheckInService versionOperationsService)
- {
- this.versionOperationsService = versionOperationsService;
- }
-
- /**
- * @return Returns the ContentService.
- */
- public ContentService getContentService()
- {
- return this.contentService;
- }
-
- /**
- * @param contentService The ContentService to set.
- */
- public void setContentService(ContentService contentService)
- {
- this.contentService = contentService;
- }
-
- /**
- * @return The document node being used for the current operation
- */
- public Node getDocument()
- {
- return this.document;
- }
-
- /**
- * @param document The document node to be used for the current operation
- */
- public void setDocument(Node document)
- {
- this.document = document;
- }
-
- /**
- * @return Returns the working copy Document.
- */
- public Node getWorkingDocument()
- {
- return this.workingDocument;
- }
-
- /**
- * @param workingDocument The working copy Document to set.
- */
- public void setWorkingDocument(Node workingDocument)
- {
- this.workingDocument = workingDocument;
- }
-
- /**
- * Determines whether the document being checked in has
- * the versionable aspect applied
- *
- * @return true if the versionable aspect is applied
- */
- public boolean isVersionable()
- {
- return getDocument().hasAspect(ContentModel.ASPECT_VERSIONABLE);
- }
-
- /**
- * @param keepCheckedOut The keepCheckedOut to set.
- */
- public void setKeepCheckedOut(boolean keepCheckedOut)
- {
- this.keepCheckedOut = keepCheckedOut;
- }
-
- /**
- * @return Returns the keepCheckedOut.
- */
- public boolean getKeepCheckedOut()
- {
- return this.keepCheckedOut;
- }
-
- /**
- * @param minorChange The minorChange to set.
- */
- public void setMinorChange(boolean minorChange)
- {
- this.minorChange = minorChange;
- }
-
- /**
- * @return Returns the minorChange flag.
- */
- public boolean getMinorChange()
- {
- return this.minorChange;
- }
-
- /**
- * @return Returns the version history notes.
- */
- public String getVersionNotes()
- {
- return this.versionNotes;
- }
-
- /**
- * @param versionNotes The version history notes to set.
- */
- public void setVersionNotes(String versionNotes)
- {
- this.versionNotes = versionNotes;
- }
-
- /**
- * @return Returns the selected Space Id.
- */
- public NodeRef getSelectedSpaceId()
- {
- return this.selectedSpaceId;
- }
-
- /**
- * @param selectedSpaceId The selected Space Id to set.
- */
- public void setSelectedSpaceId(NodeRef selectedSpaceId)
- {
- this.selectedSpaceId = selectedSpaceId;
- }
-
- /**
- * @return Returns the copy location. Either the current or other space.
- */
- public String getCopyLocation()
- {
- if (this.fileName != null)
- {
- return CheckinCheckoutBean.COPYLOCATION_OTHER;
- }
- else
- {
- return this.copyLocation;
- }
- }
-
- /**
- * @param copyLocation The copy location. Either the current or other space.
- */
- public void setCopyLocation(String copyLocation)
- {
- this.copyLocation = copyLocation;
- }
-
- /**
- * @return Returns the message to display when a file has been uploaded
- */
- public String getFileUploadSuccessMsg()
- {
- String msg = Application.getMessage(FacesContext.getCurrentInstance(), "file_upload_success");
- return MessageFormat.format(msg, new Object[] {getFileName()});
- }
-
- /**
- * @return Returns the name of the file
- */
- public String getFileName()
- {
- // try and retrieve the file and filename from the file upload bean
- // representing the file we previously uploaded.
- FacesContext ctx = FacesContext.getCurrentInstance();
- FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap().
- get(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
- if (fileBean != null)
- {
- this.file = fileBean.getFile();
- this.fileName = fileBean.getFileName();
- }
-
- return this.fileName;
- }
-
- /**
- * @param fileName The name of the file
- */
- public void setFileName(String fileName)
- {
- this.fileName = fileName;
-
- // we also need to keep the file upload bean in sync
- FacesContext ctx = FacesContext.getCurrentInstance();
- FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap().
- get(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
- if (fileBean != null)
- {
- fileBean.setFileName(this.fileName);
- }
- }
-
- /**
- * @return Returns the document content used for HTML in-line editing.
- */
- public String getDocumentContent()
- {
- return this.documentContent;
- }
-
- /**
- * @param documentContent The document content for HTML in-line editing.
- */
- public void setDocumentContent(String documentContent)
- {
- this.documentContent = documentContent;
- }
-
- /**
- * @return Returns output from the in-line editor page.
- */
- public String getEditorOutput()
- {
- return this.editorOutput;
- }
-
- /**
- * @param editorOutput The output from the in-line editor page
- */
- public void setEditorOutput(String editorOutput)
- {
- this.editorOutput = editorOutput;
- }
-
-
- // ------------------------------------------------------------------------------
- // Navigation action event handlers
-
- /**
- * Action event called by all actions that need to setup a Content Document context on the
- * CheckinCheckoutBean before an action page/wizard is called. The context will be a Node in
- * setDocument() which can be retrieved on action pages via getDocument().
- *
- * @param event ActionEvent
- */
- public void setupContentAction(ActionEvent event)
- {
- UIActionLink link = (UIActionLink)event.getComponent();
- Map params = link.getParameterMap();
- String id = params.get("id");
- if (id != null && id.length() != 0)
- {
- setupContentDocument(id);
- }
- else
- {
- setDocument(null);
- }
-
- clearUpload();
- }
-
- /**
- * Setup a content document node context
- *
- * @param id GUID of the node to setup as the content document context
- *
- * @return The Node
- */
- private Node setupContentDocument(String id)
- {
- if (LOGGER.isDebugEnabled())
- LOGGER.debug("Setup for action, setting current document to: " + id);
-
- Node node = null;
-
- try
- {
- // create the node ref, then our node representation
- NodeRef ref = new NodeRef(Repository.getStoreRef(), id);
- node = new Node(ref);
-
- // create content URL to the content download servlet with ID and expected filename
- // the myfile part will be ignored by the servlet but gives the browser a hint
- String url = DownloadContentServlet.generateDownloadURL(ref, node.getName());
- node.getProperties().put("url", url);
- node.getProperties().put("workingCopy", node.hasAspect(ContentModel.ASPECT_WORKING_COPY));
- node.getProperties().put("fileType32", Utils.getFileTypeImage(node.getName(), false));
-
- // remember the document
- setDocument(node);
-
- // refresh the UI, calling this method now is fine as it basically makes sure certain
- // beans clear the state - so when we finish here other beans will have been reset
- UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans();
- }
- catch (InvalidNodeRefException refErr)
- {
- Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
- FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {id}) );
- }
-
- return node;
- }
-
- /**
- * Action called upon completion of the Check Out file page
- */
- public String checkoutFile()
- {
- String outcome = null;
-
- UserTransaction tx = null;
-
- Node node = getDocument();
- if (node != null)
- {
- try
- {
- tx = Repository.getUserTransaction(FacesContext.getCurrentInstance());
- tx.begin();
-
- if (LOGGER.isDebugEnabled())
- LOGGER.debug("Trying to checkout content node Id: " + node.getId());
-
- // checkout the node content to create a working copy
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("Checkout copy location: " + getCopyLocation());
- LOGGER.debug("Selected Space Id: " + this.selectedSpaceId);
- }
- NodeRef workingCopyRef;
- if (getCopyLocation().equals(COPYLOCATION_OTHER) && this.selectedSpaceId != null)
- {
- // checkout to a arbituary parent Space
- NodeRef destRef = this.selectedSpaceId;
-
- ChildAssociationRef childAssocRef = this.nodeService.getPrimaryParent(destRef);
- workingCopyRef = this.versionOperationsService.checkout(node.getNodeRef(),
- destRef, ContentModel.ASSOC_CONTAINS, childAssocRef.getQName());
- }
- else
- {
- workingCopyRef = this.versionOperationsService.checkout(node.getNodeRef());
- }
-
- // set the working copy Node instance
- Node workingCopy = new Node(workingCopyRef);
- setWorkingDocument(workingCopy);
-
- // create content URL to the content download servlet with ID and expected filename
- // the myfile part will be ignored by the servlet but gives the browser a hint
- String url = DownloadContentServlet.generateDownloadURL(workingCopyRef, workingCopy.getName());
-
- workingCopy.getProperties().put("url", url);
- workingCopy.getProperties().put("fileType32", Utils.getFileTypeImage(workingCopy.getName(), false));
-
- // commit the transaction
- tx.commit();
-
- // show the page that display the checkout link
- outcome = "checkoutFileLink";
- }
- catch (Throwable err)
- {
- // rollback the transaction
- try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
- Utils.addErrorMessage(Application.getMessage(
- FacesContext.getCurrentInstance(), MSG_ERROR_CHECKOUT) + err.getMessage(), err);
- }
- }
- else
- {
- LOGGER.warn("WARNING: checkoutFile called without a current Document!");
- }
-
- return outcome;
- }
-
- /**
- * Action called upon completion of the Check Out file Link download page
- */
- public String checkoutFileOK()
- {
- String outcome = null;
-
- Node node = getWorkingDocument();
- if (node != null)
- {
- // reset the underlying node
- if (this.browseBean.getDocument() != null)
- {
- this.browseBean.getDocument().reset();
- }
-
- // clean up and clear action context
- clearUpload();
- setDocument(null);
- setWorkingDocument(null);
-
- outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
- }
- else
- {
- LOGGER.warn("WARNING: checkoutFileOK called without a current WorkingDocument!");
- }
-
- return outcome;
- }
-
- /**
- * Action called upon completion of the Edit File download page
- */
- public String editFileOK()
- {
- String outcome = null;
-
- Node node = getDocument();
- if (node != null)
- {
- // clean up and clear action context
- clearUpload();
- setDocument(null);
- setWorkingDocument(null);
-
- outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
- }
- else
- {
- LOGGER.warn("WARNING: editFileOK called without a current Document!");
- }
-
- return outcome;
- }
-
- /**
- * Action handler called to calculate which editing screen to display based on the mimetype
- * of a document. If appropriate, the in-line editing screen will be shown.
- */
- public void editFile(ActionEvent event)
- {
- UIActionLink link = (UIActionLink)event.getComponent();
- Map params = link.getParameterMap();
- String id = params.get("id");
- if (id != null && id.length() != 0)
- {
- boolean editingInline = false;
- Node node = setupContentDocument(id);
-
- // detect the inline editing aspect to see which edit mode to use
- if (node.hasAspect(ContentModel.ASPECT_INLINEEDITABLE) &&
- node.getProperties().get(ContentModel.PROP_EDITINLINE) != null &&
- ((Boolean)node.getProperties().get(ContentModel.PROP_EDITINLINE)).booleanValue() == true)
- {
- // retrieve the content reader for this node
- ContentReader reader = getContentService().getReader(node.getNodeRef(), ContentModel.PROP_CONTENT);
- if (reader != null)
- {
- editingInline = true;
- String mimetype = reader.getMimetype();
-
- // calculate which editor screen to display
- if (MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(mimetype) ||
- MimetypeMap.MIMETYPE_XML.equals(mimetype) ||
- MimetypeMap.MIMETYPE_TEXT_CSS.equals(mimetype) ||
- MimetypeMap.MIMETYPE_JAVASCRIPT.equals(mimetype))
- {
- // make content available to the editing screen
- String contentString = reader.getContentString();
- setDocumentContent(contentString);
- setEditorOutput(contentString);
-
- // navigate to appropriate screen
- FacesContext fc = FacesContext.getCurrentInstance();
- this.navigator.setupDispatchContext(node);
- String s = (MimetypeMap.MIMETYPE_XML.equals(mimetype)
- ? "dialog:editXmlInline"
- : "dialog:editTextInline");
- fc.getApplication().getNavigationHandler().handleNavigation(fc, null, s);
-
- }
- else
- {
- // make content available to the editing screen
- setDocumentContent(reader.getContentString());
- setEditorOutput(null);
-
- // navigate to appropriate screen
- FacesContext fc = FacesContext.getCurrentInstance();
- this.navigator.setupDispatchContext(node);
- fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editHtmlInline");
- }
- }
- }
-
- if (editingInline == false)
- {
- // normal downloadable document
- FacesContext fc = FacesContext.getCurrentInstance();
- this.navigator.setupDispatchContext(node);
- fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editFile");
- }
- }
- }
-
- /**
- * Action handler called to set the content of a node from an inline editing page.
- */
- public String editInlineOK()
- {
- String outcome = null;
-
- UserTransaction tx = null;
-
- Node node = getDocument();
- if (node != null)
- {
- try
- {
- tx = Repository.getUserTransaction(FacesContext.getCurrentInstance());
- tx.begin();
-
- if (LOGGER.isDebugEnabled())
- LOGGER.debug("Trying to update content node Id: " + node.getId());
-
- // get an updating writer that we can use to modify the content on the current node
- ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true);
- writer.putContent(this.editorOutput);
-
- // commit the transaction
- tx.commit();
-
- if (nodeService.getProperty(node.getNodeRef(),
- TemplatingService.TT_QNAME) != null)
- {
- OutputUtil.regenerate(node.getNodeRef(),
- this.contentService,
- this.nodeService);
- }
-
- // clean up and clear action context
- clearUpload();
- setDocument(null);
- setDocumentContent(null);
- setEditorOutput(null);
-
- outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
- }
- catch (Throwable err)
- {
- // rollback the transaction
- try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
- Utils.addErrorMessage(Application.getMessage(
- FacesContext.getCurrentInstance(), MSG_ERROR_UPDATE) + err.getMessage());
- }
- }
- else
- {
- LOGGER.warn("WARNING: editInlineOK called without a current Document!");
- }
-
- return outcome;
- }
-
- /**
- * Action to undo the checkout of a document just checked out from the checkout screen.
- */
- public String undoCheckout()
- {
- String outcome = null;
-
- Node node = getWorkingDocument();
- if (node != null)
- {
- try
- {
- // try to cancel checkout of the working copy
- this.versionOperationsService.cancelCheckout(node.getNodeRef());
-
- clearUpload();
-
- outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
- }
- catch (Throwable err)
- {
- Utils.addErrorMessage(Application.getMessage(
- FacesContext.getCurrentInstance(), MSG_ERROR_CANCELCHECKOUT) + err.getMessage(), err);
- }
- }
- else
- {
- LOGGER.warn("WARNING: undoCheckout called without a current WorkingDocument!");
- }
-
- return outcome;
- }
-
- /**
- * Action to undo the checkout of a locked document. This document may either by the original copy
- * or the working copy node. Therefore calculate which it is, if the working copy is found then
- * we simply cancel checkout on that document. If the original copy is found then we need to find
- * the appropriate working copy and perform the action on that node.
- */
- public String undoCheckoutFile()
- {
- String outcome = null;
-
- Node node = getDocument();
- if (node != null)
- {
- try
- {
- if (node.hasAspect(ContentModel.ASPECT_WORKING_COPY))
- {
- this.versionOperationsService.cancelCheckout(node.getNodeRef());
- }
- else if (node.hasAspect(ContentModel.ASPECT_LOCKABLE))
- {
- // TODO: find the working copy for this document and cancel the checkout on it
- // is this possible? as currently only the workingcopy aspect has the copyReference
- // attribute - this means we cannot find out where the copy is to cancel it!
- // can we construct an XPath node lookup?
- throw new RuntimeException("NOT IMPLEMENTED");
- }
- else
- {
- throw new IllegalStateException("Node supplied for undo checkout has neither Working Copy or Locked aspect!");
- }
-
- clearUpload();
-
- outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse";
- }
- catch (Throwable err)
- {
- Utils.addErrorMessage(MSG_ERROR_CANCELCHECKOUT + err.getMessage(), err);
- }
- }
- else
- {
- LOGGER.warn("WARNING: undoCheckout called without a current WorkingDocument!");
- }
-
- return outcome;
- }
-
- /**
- * Action called upon completion of the Check In file page
- */
- public String checkinFileOK()
- {
- String outcome = null;
-
- UserTransaction tx = null;
-
- // NOTE: for checkin the document node _is_ the working document!
- Node node = getDocument();
- if (node != null && (getCopyLocation().equals(COPYLOCATION_CURRENT) || this.getFileName() != null))
- {
- try
- {
- FacesContext context = FacesContext.getCurrentInstance();
- tx = Repository.getUserTransaction(context);
- tx.begin();
-
- if (LOGGER.isDebugEnabled())
- LOGGER.debug("Trying to checkin content node Id: " + node.getId());
-
- // we can either checkin the content from the current working copy node
- // which would have been previously updated by the user
- String contentUrl;
- if (getCopyLocation().equals(COPYLOCATION_CURRENT))
- {
- ContentData contentData = (ContentData) node.getProperties().get(ContentModel.PROP_CONTENT);
- contentUrl = (contentData == null ? null : contentData.getContentUrl());
- }
- // or specify a specific file as the content instead
- else
- {
- // add the content to an anonymous but permanent writer location
- // we can then retrieve the URL to the content to to be set on the node during checkin
- ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true);
- // also update the mime type in case a different type of file is uploaded
- String mimeType = Repository.getMimeTypeForFileName(context, this.fileName);
- writer.setMimetype(mimeType);
- writer.putContent(this.file);
- contentUrl = writer.getContentUrl();
- }
-
- if (contentUrl == null || contentUrl.length() == 0)
- {
- throw new IllegalStateException("Content URL is empty for specified working copy content node!");
- }
-
- // add version history text to props
- Map props = new HashMap(1, 1.0f);
- props.put(Version.PROP_DESCRIPTION, this.versionNotes);
- // set the flag for minor or major change
- if (this.minorChange)
- {
- props.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
- }
- else
- {
- props.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
- }
-
- // perform the checkin
- this.versionOperationsService.checkin(node.getNodeRef(),
- props, contentUrl, this.keepCheckedOut);
-
- // commit the transaction
- tx.commit();
-
- // clear action context
- setDocument(null);
- clearUpload();
-
- outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME +
- AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse";
- }
- catch (Throwable err)
- {
- // rollback the transaction
- try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
- Utils.addErrorMessage(Application.getMessage(
- FacesContext.getCurrentInstance(), MSG_ERROR_CHECKIN) + err.getMessage(), err);
- }
- }
- else
- {
- LOGGER.warn("WARNING: checkinFileOK called without a current Document!");
- }
-
- return outcome;
- }
-
- /**
- * Action called upon completion of the Update File page
- */
- public String updateFileOK()
- {
- String outcome = null;
-
- UserTransaction tx = null;
-
- // NOTE: for update the document node _is_ the working document!
- Node node = getDocument();
- if (node != null && this.getFileName() != null)
- {
- try
- {
- FacesContext context = FacesContext.getCurrentInstance();
- tx = Repository.getUserTransaction(context);
- tx.begin();
-
- if (LOGGER.isDebugEnabled())
- LOGGER.debug("Trying to update content node Id: " + node.getId());
-
- // get an updating writer that we can use to modify the content on the current node
- ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true);
-
- // also update the mime type in case a different type of file is uploaded
- String mimeType = Repository.getMimeTypeForFileName(context, this.fileName);
- writer.setMimetype(mimeType);
-
- writer.putContent(this.file);
-
- // commit the transaction
- tx.commit();
-
- // clear action context
- setDocument(null);
- clearUpload();
-
- outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
- }
- catch (Throwable err)
- {
- // rollback the transaction
- try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
- Utils.addErrorMessage(Application.getMessage(
- FacesContext.getCurrentInstance(), MSG_ERROR_UPDATE) + err.getMessage(), err);
- }
- }
- else
- {
- LOGGER.warn("WARNING: updateFileOK called without a current Document!");
- }
-
- return outcome;
- }
-
- /**
- * Deals with the cancel button being pressed on the check in file page
- */
- public String cancel()
- {
- // reset the state
- clearUpload();
-
- return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
- }
-
- /**
- * Clear form state and upload file bean
- */
- private void clearUpload()
- {
- // delete the temporary file we uploaded earlier
- if (this.file != null)
- {
- this.file.delete();
- }
-
- this.file = null;
- this.fileName = null;
- this.keepCheckedOut = false;
- this.minorChange = true;
- this.copyLocation = COPYLOCATION_CURRENT;
- this.versionNotes = "";
- this.selectedSpaceId = null;
-
- // remove the file upload bean from the session
- FacesContext ctx = FacesContext.getCurrentInstance();
- ctx.getExternalContext().getSessionMap().remove(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
- }
-
-
- // ------------------------------------------------------------------------------
- // Private data
-
- private static final Log LOGGER = LogFactory.getLog(CheckinCheckoutBean.class);
-
- /** I18N messages */
- private static final String MSG_ERROR_CHECKIN = "error_checkin";
- private static final String MSG_ERROR_CANCELCHECKOUT = "error_cancel_checkout";
- private static final String MSG_ERROR_UPDATE = "error_update";
- private static final String MSG_ERROR_CHECKOUT = "error_checkout";
-
- /** constants for copy location selection */
- private static final String COPYLOCATION_CURRENT = "current";
- private static final String COPYLOCATION_OTHER = "other";
-
- /** The current document */
- private Node document;
-
- /** The working copy of the document we are checking out */
- private Node workingDocument;
-
- /** Content of the document used for HTML in-line editing */
- private String documentContent;
-
- /** Content of the document returned from in-line editing */
- private String editorOutput;
-
- /** transient form and upload properties */
- private File file;
- private String fileName;
- private boolean keepCheckedOut = false;
- private boolean minorChange = true;
- private String copyLocation = COPYLOCATION_CURRENT;
- private String versionNotes = "";
- private NodeRef selectedSpaceId = null;
-
- /** The BrowseBean to be used by the bean */
- protected BrowseBean browseBean;
-
- /** The NavigationBean bean reference */
- protected NavigationBean navigator;
-
- /** The NodeService to be used by the bean */
- protected NodeService nodeService;
-
- /** The VersionOperationsService to be used by the bean */
- protected CheckOutCheckInService versionOperationsService;
-
- /** The ContentService to be used by the bean */
- protected ContentService contentService;
-}
+/*
+ * Copyright (C) 2005 Alfresco, Inc.
+ *
+ * Licensed under the Mozilla Public License version 1.1
+ * with a permitted attribution clause. You may obtain a
+ * copy of the License at
+ *
+ * http://www.alfresco.org/legal/license.txt
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the
+ * License.
+ */
+package org.alfresco.web.bean;
+
+import java.io.File;
+import java.io.Serializable;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.faces.context.FacesContext;
+import javax.faces.event.ActionEvent;
+import javax.transaction.UserTransaction;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.content.MimetypeMap;
+import org.alfresco.repo.version.VersionModel;
+import org.alfresco.service.cmr.coci.CheckOutCheckInService;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.ContentData;
+import org.alfresco.service.cmr.repository.ContentReader;
+import org.alfresco.service.cmr.repository.ContentService;
+import org.alfresco.service.cmr.repository.ContentWriter;
+import org.alfresco.service.cmr.repository.InvalidNodeRefException;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.version.Version;
+import org.alfresco.service.cmr.version.VersionType;
+import org.alfresco.web.app.AlfrescoNavigationHandler;
+import org.alfresco.web.app.Application;
+import org.alfresco.web.app.context.UIContextService;
+import org.alfresco.web.app.servlet.DownloadContentServlet;
+import org.alfresco.web.bean.repository.Node;
+import org.alfresco.web.bean.repository.Repository;
+import org.alfresco.web.templating.OutputUtil;
+import org.alfresco.web.templating.TemplatingService;
+import org.alfresco.web.ui.common.Utils;
+import org.alfresco.web.ui.common.component.UIActionLink;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author Kevin Roast
+ */
+public class CheckinCheckoutBean
+{
+ // ------------------------------------------------------------------------------
+ // Bean property getters and setters
+
+ /**
+ * @param navigator The NavigationBean to set.
+ */
+ public void setNavigator(NavigationBean navigator)
+ {
+ this.navigator = navigator;
+ }
+
+ /**
+ * @return Returns the BrowseBean.
+ */
+ public BrowseBean getBrowseBean()
+ {
+ return this.browseBean;
+ }
+
+ /**
+ * @param browseBean The BrowseBean to set.
+ */
+ public void setBrowseBean(BrowseBean browseBean)
+ {
+ this.browseBean = browseBean;
+ }
+
+ /**
+ * @return Returns the NodeService.
+ */
+ public NodeService getNodeService()
+ {
+ return this.nodeService;
+ }
+
+ /**
+ * @param nodeService The NodeService to set.
+ */
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ /**
+ * @return Returns the VersionOperationsService.
+ */
+ public CheckOutCheckInService getVersionOperationsService()
+ {
+ return this.versionOperationsService;
+ }
+
+ /**
+ * @param versionOperationsService The VersionOperationsService to set.
+ */
+ public void setVersionOperationsService(CheckOutCheckInService versionOperationsService)
+ {
+ this.versionOperationsService = versionOperationsService;
+ }
+
+ /**
+ * @return Returns the ContentService.
+ */
+ public ContentService getContentService()
+ {
+ return this.contentService;
+ }
+
+ /**
+ * @param contentService The ContentService to set.
+ */
+ public void setContentService(ContentService contentService)
+ {
+ this.contentService = contentService;
+ }
+
+ /**
+ * @return The document node being used for the current operation
+ */
+ public Node getDocument()
+ {
+ return this.document;
+ }
+
+ /**
+ * @param document The document node to be used for the current operation
+ */
+ public void setDocument(Node document)
+ {
+ this.document = document;
+ }
+
+ /**
+ * @return Returns the working copy Document.
+ */
+ public Node getWorkingDocument()
+ {
+ return this.workingDocument;
+ }
+
+ /**
+ * @param workingDocument The working copy Document to set.
+ */
+ public void setWorkingDocument(Node workingDocument)
+ {
+ this.workingDocument = workingDocument;
+ }
+
+ /**
+ * Determines whether the document being checked in has
+ * the versionable aspect applied
+ *
+ * @return true if the versionable aspect is applied
+ */
+ public boolean isVersionable()
+ {
+ return getDocument().hasAspect(ContentModel.ASPECT_VERSIONABLE);
+ }
+
+ /**
+ * @param keepCheckedOut The keepCheckedOut to set.
+ */
+ public void setKeepCheckedOut(boolean keepCheckedOut)
+ {
+ this.keepCheckedOut = keepCheckedOut;
+ }
+
+ /**
+ * @return Returns the keepCheckedOut.
+ */
+ public boolean getKeepCheckedOut()
+ {
+ return this.keepCheckedOut;
+ }
+
+ /**
+ * @param minorChange The minorChange to set.
+ */
+ public void setMinorChange(boolean minorChange)
+ {
+ this.minorChange = minorChange;
+ }
+
+ /**
+ * @return Returns the minorChange flag.
+ */
+ public boolean getMinorChange()
+ {
+ return this.minorChange;
+ }
+
+ /**
+ * @return Returns the version history notes.
+ */
+ public String getVersionNotes()
+ {
+ return this.versionNotes;
+ }
+
+ /**
+ * @param versionNotes The version history notes to set.
+ */
+ public void setVersionNotes(String versionNotes)
+ {
+ this.versionNotes = versionNotes;
+ }
+
+ /**
+ * @return Returns the selected Space Id.
+ */
+ public NodeRef getSelectedSpaceId()
+ {
+ return this.selectedSpaceId;
+ }
+
+ /**
+ * @param selectedSpaceId The selected Space Id to set.
+ */
+ public void setSelectedSpaceId(NodeRef selectedSpaceId)
+ {
+ this.selectedSpaceId = selectedSpaceId;
+ }
+
+ /**
+ * @return Returns the copy location. Either the current or other space.
+ */
+ public String getCopyLocation()
+ {
+ if (this.fileName != null)
+ {
+ return CheckinCheckoutBean.COPYLOCATION_OTHER;
+ }
+ else
+ {
+ return this.copyLocation;
+ }
+ }
+
+ /**
+ * @param copyLocation The copy location. Either the current or other space.
+ */
+ public void setCopyLocation(String copyLocation)
+ {
+ this.copyLocation = copyLocation;
+ }
+
+ /**
+ * @return Returns the message to display when a file has been uploaded
+ */
+ public String getFileUploadSuccessMsg()
+ {
+ String msg = Application.getMessage(FacesContext.getCurrentInstance(), "file_upload_success");
+ return MessageFormat.format(msg, new Object[] {getFileName()});
+ }
+
+ /**
+ * @return Returns the name of the file
+ */
+ public String getFileName()
+ {
+ // try and retrieve the file and filename from the file upload bean
+ // representing the file we previously uploaded.
+ FacesContext ctx = FacesContext.getCurrentInstance();
+ FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap().
+ get(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
+ if (fileBean != null)
+ {
+ this.file = fileBean.getFile();
+ this.fileName = fileBean.getFileName();
+ }
+
+ return this.fileName;
+ }
+
+ /**
+ * @param fileName The name of the file
+ */
+ public void setFileName(String fileName)
+ {
+ this.fileName = fileName;
+
+ // we also need to keep the file upload bean in sync
+ FacesContext ctx = FacesContext.getCurrentInstance();
+ FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap().
+ get(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
+ if (fileBean != null)
+ {
+ fileBean.setFileName(this.fileName);
+ }
+ }
+
+ /**
+ * @return Returns the document content used for HTML in-line editing.
+ */
+ public String getDocumentContent()
+ {
+ return this.documentContent;
+ }
+
+ /**
+ * @param documentContent The document content for HTML in-line editing.
+ */
+ public void setDocumentContent(String documentContent)
+ {
+ this.documentContent = documentContent;
+ }
+
+ /**
+ * @return Returns output from the in-line editor page.
+ */
+ public String getEditorOutput()
+ {
+ return this.editorOutput;
+ }
+
+ /**
+ * @param editorOutput The output from the in-line editor page
+ */
+ public void setEditorOutput(String editorOutput)
+ {
+ this.editorOutput = editorOutput;
+ }
+
+
+ // ------------------------------------------------------------------------------
+ // Navigation action event handlers
+
+ /**
+ * Action event called by all actions that need to setup a Content Document context on the
+ * CheckinCheckoutBean before an action page/wizard is called. The context will be a Node in
+ * setDocument() which can be retrieved on action pages via getDocument().
+ *
+ * @param event ActionEvent
+ */
+ public void setupContentAction(ActionEvent event)
+ {
+ UIActionLink link = (UIActionLink)event.getComponent();
+ Map params = link.getParameterMap();
+ String id = params.get("id");
+ if (id != null && id.length() != 0)
+ {
+ setupContentDocument(id);
+ }
+ else
+ {
+ setDocument(null);
+ }
+
+ clearUpload();
+ }
+
+ /**
+ * Setup a content document node context
+ *
+ * @param id GUID of the node to setup as the content document context
+ *
+ * @return The Node
+ */
+ private Node setupContentDocument(String id)
+ {
+ if (logger.isDebugEnabled())
+ logger.debug("Setup for action, setting current document to: " + id);
+
+ Node node = null;
+
+ try
+ {
+ // create the node ref, then our node representation
+ NodeRef ref = new NodeRef(Repository.getStoreRef(), id);
+ node = new Node(ref);
+
+ // create content URL to the content download servlet with ID and expected filename
+ // the myfile part will be ignored by the servlet but gives the browser a hint
+ String url = DownloadContentServlet.generateDownloadURL(ref, node.getName());
+ node.getProperties().put("url", url);
+ node.getProperties().put("workingCopy", node.hasAspect(ContentModel.ASPECT_WORKING_COPY));
+ node.getProperties().put("fileType32", Utils.getFileTypeImage(node.getName(), false));
+
+ // remember the document
+ setDocument(node);
+
+ // refresh the UI, calling this method now is fine as it basically makes sure certain
+ // beans clear the state - so when we finish here other beans will have been reset
+ UIContextService.getInstance(FacesContext.getCurrentInstance()).notifyBeans();
+ }
+ catch (InvalidNodeRefException refErr)
+ {
+ Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
+ FacesContext.getCurrentInstance(), Repository.ERROR_NODEREF), new Object[] {id}) );
+ }
+
+ return node;
+ }
+
+ /**
+ * Action called upon completion of the Check Out file page
+ */
+ public String checkoutFile()
+ {
+ String outcome = null;
+
+ UserTransaction tx = null;
+
+ Node node = getDocument();
+ if (node != null)
+ {
+ try
+ {
+ tx = Repository.getUserTransaction(FacesContext.getCurrentInstance());
+ tx.begin();
+
+ if (logger.isDebugEnabled())
+ logger.debug("Trying to checkout content node Id: " + node.getId());
+
+ // checkout the node content to create a working copy
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Checkout copy location: " + getCopyLocation());
+ logger.debug("Selected Space Id: " + this.selectedSpaceId);
+ }
+ NodeRef workingCopyRef;
+ if (getCopyLocation().equals(COPYLOCATION_OTHER) && this.selectedSpaceId != null)
+ {
+ // checkout to a arbituary parent Space
+ NodeRef destRef = this.selectedSpaceId;
+
+ ChildAssociationRef childAssocRef = this.nodeService.getPrimaryParent(destRef);
+ workingCopyRef = this.versionOperationsService.checkout(node.getNodeRef(),
+ destRef, ContentModel.ASSOC_CONTAINS, childAssocRef.getQName());
+ }
+ else
+ {
+ workingCopyRef = this.versionOperationsService.checkout(node.getNodeRef());
+ }
+
+ // set the working copy Node instance
+ Node workingCopy = new Node(workingCopyRef);
+ setWorkingDocument(workingCopy);
+
+ // create content URL to the content download servlet with ID and expected filename
+ // the myfile part will be ignored by the servlet but gives the browser a hint
+ String url = DownloadContentServlet.generateDownloadURL(workingCopyRef, workingCopy.getName());
+
+ workingCopy.getProperties().put("url", url);
+ workingCopy.getProperties().put("fileType32", Utils.getFileTypeImage(workingCopy.getName(), false));
+
+ // commit the transaction
+ tx.commit();
+
+ // show the page that display the checkout link
+ outcome = "checkoutFileLink";
+ }
+ catch (Throwable err)
+ {
+ // rollback the transaction
+ try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
+ Utils.addErrorMessage(Application.getMessage(
+ FacesContext.getCurrentInstance(), MSG_ERROR_CHECKOUT) + err.getMessage(), err);
+ }
+ }
+ else
+ {
+ logger.warn("WARNING: checkoutFile called without a current Document!");
+ }
+
+ return outcome;
+ }
+
+ /**
+ * Action called upon completion of the Check Out file Link download page
+ */
+ public String checkoutFileOK()
+ {
+ String outcome = null;
+
+ Node node = getWorkingDocument();
+ if (node != null)
+ {
+ // reset the underlying node
+ if (this.browseBean.getDocument() != null)
+ {
+ this.browseBean.getDocument().reset();
+ }
+
+ // clean up and clear action context
+ clearUpload();
+ setDocument(null);
+ setWorkingDocument(null);
+
+ outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
+ }
+ else
+ {
+ logger.warn("WARNING: checkoutFileOK called without a current WorkingDocument!");
+ }
+
+ return outcome;
+ }
+
+ /**
+ * Action called upon completion of the Edit File download page
+ */
+ public String editFileOK()
+ {
+ String outcome = null;
+
+ Node node = getDocument();
+ if (node != null)
+ {
+ // clean up and clear action context
+ clearUpload();
+ setDocument(null);
+ setWorkingDocument(null);
+
+ outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
+ }
+ else
+ {
+ logger.warn("WARNING: editFileOK called without a current Document!");
+ }
+
+ return outcome;
+ }
+
+ /**
+ * Action handler called to calculate which editing screen to display based on the mimetype
+ * of a document. If appropriate, the in-line editing screen will be shown.
+ */
+ public void editFile(ActionEvent event)
+ {
+ UIActionLink link = (UIActionLink)event.getComponent();
+ Map params = link.getParameterMap();
+ String id = params.get("id");
+ if (id != null && id.length() != 0)
+ {
+ boolean editingInline = false;
+ Node node = setupContentDocument(id);
+
+ // detect the inline editing aspect to see which edit mode to use
+ if (node.hasAspect(ContentModel.ASPECT_INLINEEDITABLE) &&
+ node.getProperties().get(ContentModel.PROP_EDITINLINE) != null &&
+ ((Boolean)node.getProperties().get(ContentModel.PROP_EDITINLINE)).booleanValue() == true)
+ {
+ // retrieve the content reader for this node
+ ContentReader reader = getContentService().getReader(node.getNodeRef(), ContentModel.PROP_CONTENT);
+ if (reader != null)
+ {
+ editingInline = true;
+ String mimetype = reader.getMimetype();
+
+ // calculate which editor screen to display
+ if (MimetypeMap.MIMETYPE_TEXT_PLAIN.equals(mimetype) ||
+ MimetypeMap.MIMETYPE_XML.equals(mimetype) ||
+ MimetypeMap.MIMETYPE_TEXT_CSS.equals(mimetype) ||
+ MimetypeMap.MIMETYPE_JAVASCRIPT.equals(mimetype))
+ {
+ // make content available to the editing screen
+ setEditorOutput(reader.getContentString());
+
+ // navigate to appropriate screen
+ FacesContext fc = FacesContext.getCurrentInstance();
+ this.navigator.setupDispatchContext(node);
+ String s = (MimetypeMap.MIMETYPE_XML.equals(mimetype)
+ ? "dialog:editXmlInline"
+ : "dialog:editTextInline");
+ fc.getApplication().getNavigationHandler().handleNavigation(fc, null, s);
+
+ }
+ else
+ {
+ // make content available to the editing screen
+ setDocumentContent(reader.getContentString());
+ setEditorOutput(null);
+
+ // navigate to appropriate screen
+ FacesContext fc = FacesContext.getCurrentInstance();
+ this.navigator.setupDispatchContext(node);
+ fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editHtmlInline");
+ }
+ }
+ }
+
+ if (editingInline == false)
+ {
+ // normal downloadable document
+ FacesContext fc = FacesContext.getCurrentInstance();
+ this.navigator.setupDispatchContext(node);
+ fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editFile");
+ }
+ }
+ }
+
+ /**
+ * Action handler called to set the content of a node from an inline editing page.
+ */
+ public String editInlineOK()
+ {
+ String outcome = null;
+
+ UserTransaction tx = null;
+
+ Node node = getDocument();
+ if (node != null)
+ {
+ try
+ {
+ tx = Repository.getUserTransaction(FacesContext.getCurrentInstance());
+ tx.begin();
+
+ if (logger.isDebugEnabled())
+ logger.debug("Trying to update content node Id: " + node.getId());
+
+ // get an updating writer that we can use to modify the content on the current node
+ ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true);
+ writer.putContent(this.editorOutput);
+
+ // commit the transaction
+ tx.commit();
+
+ if (nodeService.getProperty(node.getNodeRef(),
+ TemplatingService.TT_QNAME) != null)
+ {
+ OutputUtil.regenerate(node.getNodeRef(),
+ this.contentService,
+ this.nodeService);
+ }
+
+ // clean up and clear action context
+ clearUpload();
+ setDocument(null);
+ setDocumentContent(null);
+ setEditorOutput(null);
+
+ outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
+ }
+ catch (Throwable err)
+ {
+ // rollback the transaction
+ try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
+ Utils.addErrorMessage(Application.getMessage(
+ FacesContext.getCurrentInstance(), MSG_ERROR_UPDATE) + err.getMessage());
+ }
+ }
+ else
+ {
+ logger.warn("WARNING: editInlineOK called without a current Document!");
+ }
+
+ return outcome;
+ }
+
+ /**
+ * Action to undo the checkout of a document just checked out from the checkout screen.
+ */
+ public String undoCheckout()
+ {
+ String outcome = null;
+
+ Node node = getWorkingDocument();
+ if (node != null)
+ {
+ try
+ {
+ // try to cancel checkout of the working copy
+ this.versionOperationsService.cancelCheckout(node.getNodeRef());
+
+ clearUpload();
+
+ outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
+ }
+ catch (Throwable err)
+ {
+ Utils.addErrorMessage(Application.getMessage(
+ FacesContext.getCurrentInstance(), MSG_ERROR_CANCELCHECKOUT) + err.getMessage(), err);
+ }
+ }
+ else
+ {
+ logger.warn("WARNING: undoCheckout called without a current WorkingDocument!");
+ }
+
+ return outcome;
+ }
+
+ /**
+ * Action to undo the checkout of a locked document. This document may either by the original copy
+ * or the working copy node. Therefore calculate which it is, if the working copy is found then
+ * we simply cancel checkout on that document. If the original copy is found then we need to find
+ * the appropriate working copy and perform the action on that node.
+ */
+ public String undoCheckoutFile()
+ {
+ String outcome = null;
+
+ Node node = getDocument();
+ if (node != null)
+ {
+ try
+ {
+ if (node.hasAspect(ContentModel.ASPECT_WORKING_COPY))
+ {
+ this.versionOperationsService.cancelCheckout(node.getNodeRef());
+ }
+ else if (node.hasAspect(ContentModel.ASPECT_LOCKABLE))
+ {
+ // TODO: find the working copy for this document and cancel the checkout on it
+ // is this possible? as currently only the workingcopy aspect has the copyReference
+ // attribute - this means we cannot find out where the copy is to cancel it!
+ // can we construct an XPath node lookup?
+ throw new RuntimeException("NOT IMPLEMENTED");
+ }
+ else
+ {
+ throw new IllegalStateException("Node supplied for undo checkout has neither Working Copy or Locked aspect!");
+ }
+
+ clearUpload();
+
+ outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME + AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse";
+ }
+ catch (Throwable err)
+ {
+ Utils.addErrorMessage(MSG_ERROR_CANCELCHECKOUT + err.getMessage(), err);
+ }
+ }
+ else
+ {
+ logger.warn("WARNING: undoCheckout called without a current WorkingDocument!");
+ }
+
+ return outcome;
+ }
+
+ /**
+ * Action called upon completion of the Check In file page
+ */
+ public String checkinFileOK()
+ {
+ String outcome = null;
+
+ UserTransaction tx = null;
+
+ // NOTE: for checkin the document node _is_ the working document!
+ Node node = getDocument();
+ if (node != null && (getCopyLocation().equals(COPYLOCATION_CURRENT) || this.getFileName() != null))
+ {
+ try
+ {
+ FacesContext context = FacesContext.getCurrentInstance();
+ tx = Repository.getUserTransaction(context);
+ tx.begin();
+
+ if (logger.isDebugEnabled())
+ logger.debug("Trying to checkin content node Id: " + node.getId());
+
+ // we can either checkin the content from the current working copy node
+ // which would have been previously updated by the user
+ String contentUrl;
+ if (getCopyLocation().equals(COPYLOCATION_CURRENT))
+ {
+ ContentData contentData = (ContentData) node.getProperties().get(ContentModel.PROP_CONTENT);
+ contentUrl = (contentData == null ? null : contentData.getContentUrl());
+ }
+ // or specify a specific file as the content instead
+ else
+ {
+ // add the content to an anonymous but permanent writer location
+ // we can then retrieve the URL to the content to to be set on the node during checkin
+ ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true);
+ // also update the mime type in case a different type of file is uploaded
+ String mimeType = Repository.getMimeTypeForFileName(context, this.fileName);
+ writer.setMimetype(mimeType);
+ writer.putContent(this.file);
+ contentUrl = writer.getContentUrl();
+ }
+
+ if (contentUrl == null || contentUrl.length() == 0)
+ {
+ throw new IllegalStateException("Content URL is empty for specified working copy content node!");
+ }
+
+ // add version history text to props
+ Map props = new HashMap(1, 1.0f);
+ props.put(Version.PROP_DESCRIPTION, this.versionNotes);
+ // set the flag for minor or major change
+ if (this.minorChange)
+ {
+ props.put(VersionModel.PROP_VERSION_TYPE, VersionType.MINOR);
+ }
+ else
+ {
+ props.put(VersionModel.PROP_VERSION_TYPE, VersionType.MAJOR);
+ }
+
+ // perform the checkin
+ this.versionOperationsService.checkin(node.getNodeRef(),
+ props, contentUrl, this.keepCheckedOut);
+
+ // commit the transaction
+ tx.commit();
+
+ // clear action context
+ setDocument(null);
+ clearUpload();
+
+ outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME +
+ AlfrescoNavigationHandler.OUTCOME_SEPARATOR + "browse";
+ }
+ catch (Throwable err)
+ {
+ // rollback the transaction
+ try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
+ Utils.addErrorMessage(Application.getMessage(
+ FacesContext.getCurrentInstance(), MSG_ERROR_CHECKIN) + err.getMessage(), err);
+ }
+ }
+ else
+ {
+ logger.warn("WARNING: checkinFileOK called without a current Document!");
+ }
+
+ return outcome;
+ }
+
+ /**
+ * Action called upon completion of the Update File page
+ */
+ public String updateFileOK()
+ {
+ String outcome = null;
+
+ UserTransaction tx = null;
+
+ // NOTE: for update the document node _is_ the working document!
+ Node node = getDocument();
+ if (node != null && this.getFileName() != null)
+ {
+ try
+ {
+ FacesContext context = FacesContext.getCurrentInstance();
+ tx = Repository.getUserTransaction(context);
+ tx.begin();
+
+ if (logger.isDebugEnabled())
+ logger.debug("Trying to update content node Id: " + node.getId());
+
+ // get an updating writer that we can use to modify the content on the current node
+ ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true);
+
+ // also update the mime type in case a different type of file is uploaded
+ String mimeType = Repository.getMimeTypeForFileName(context, this.fileName);
+ writer.setMimetype(mimeType);
+
+ writer.putContent(this.file);
+
+ // commit the transaction
+ tx.commit();
+
+ // clear action context
+ setDocument(null);
+ clearUpload();
+
+ outcome = AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
+ }
+ catch (Throwable err)
+ {
+ // rollback the transaction
+ try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
+ Utils.addErrorMessage(Application.getMessage(
+ FacesContext.getCurrentInstance(), MSG_ERROR_UPDATE) + err.getMessage(), err);
+ }
+ }
+ else
+ {
+ logger.warn("WARNING: updateFileOK called without a current Document!");
+ }
+
+ return outcome;
+ }
+
+ /**
+ * Deals with the cancel button being pressed on the check in file page
+ */
+ public String cancel()
+ {
+ // reset the state
+ clearUpload();
+
+ return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME;
+ }
+
+ /**
+ * Clear form state and upload file bean
+ */
+ private void clearUpload()
+ {
+ // delete the temporary file we uploaded earlier
+ if (this.file != null)
+ {
+ this.file.delete();
+ }
+
+ this.file = null;
+ this.fileName = null;
+ this.keepCheckedOut = false;
+ this.minorChange = true;
+ this.copyLocation = COPYLOCATION_CURRENT;
+ this.versionNotes = "";
+ this.selectedSpaceId = null;
+
+ // remove the file upload bean from the session
+ FacesContext ctx = FacesContext.getCurrentInstance();
+ ctx.getExternalContext().getSessionMap().remove(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
+ }
+
+
+ // ------------------------------------------------------------------------------
+ // Private data
+
+ private static Log logger = LogFactory.getLog(CheckinCheckoutBean.class);
+
+ /** I18N messages */
+ private static final String MSG_ERROR_CHECKIN = "error_checkin";
+ private static final String MSG_ERROR_CANCELCHECKOUT = "error_cancel_checkout";
+ private static final String MSG_ERROR_UPDATE = "error_update";
+ private static final String MSG_ERROR_CHECKOUT = "error_checkout";
+
+ /** constants for copy location selection */
+ private static final String COPYLOCATION_CURRENT = "current";
+ private static final String COPYLOCATION_OTHER = "other";
+
+ /** The current document */
+ private Node document;
+
+ /** The working copy of the document we are checking out */
+ private Node workingDocument;
+
+ /** Content of the document used for HTML in-line editing */
+ private String documentContent;
+
+ /** Content of the document returned from in-line editing */
+ private String editorOutput;
+
+ /** transient form and upload properties */
+ private File file;
+ private String fileName;
+ private boolean keepCheckedOut = false;
+ private boolean minorChange = true;
+ private String copyLocation = COPYLOCATION_CURRENT;
+ private String versionNotes = "";
+ private NodeRef selectedSpaceId = null;
+
+ /** The BrowseBean to be used by the bean */
+ protected BrowseBean browseBean;
+
+ /** The NavigationBean bean reference */
+ protected NavigationBean navigator;
+
+ /** The NodeService to be used by the bean */
+ protected NodeService nodeService;
+
+ /** The VersionOperationsService to be used by the bean */
+ protected CheckOutCheckInService versionOperationsService;
+
+ /** The ContentService to be used by the bean */
+ protected ContentService contentService;
+}
diff --git a/source/java/org/alfresco/web/bean/content/CreateContentWizard.java b/source/java/org/alfresco/web/bean/content/CreateContentWizard.java
index dd11533c0d..ca61c9a54b 100644
--- a/source/java/org/alfresco/web/bean/content/CreateContentWizard.java
+++ b/source/java/org/alfresco/web/bean/content/CreateContentWizard.java
@@ -53,14 +53,14 @@ import org.alfresco.web.app.servlet.FacesHelper;
*/
public class CreateContentWizard extends BaseContentWizard
{
- protected String content = null;
+ protected String content = null;
protected String templateTypeName;
- protected List createMimeTypes;
-
+ protected List createMimeTypes;
+
private static final Log LOGGER =
LogFactory.getLog(CreateContentWizard.class);
-
+
// ------------------------------------------------------------------------------
// Wizard implementation
@@ -69,7 +69,7 @@ public class CreateContentWizard extends BaseContentWizard
throws Exception
{
LOGGER.debug("saving file content to " + this.fileName);
- saveContent(null, this.content);
+ saveContent(null, this.content);
if (this.templateTypeName != null)
{
LOGGER.debug("generating template output for " + this.templateTypeName);
@@ -87,9 +87,9 @@ public class CreateContentWizard extends BaseContentWizard
this.contentService,
this.nodeService);
}
-
- // return the default outcome
- return outcome;
+
+ // return the default outcome
+ return outcome;
}
@Override
@@ -162,7 +162,7 @@ public class CreateContentWizard extends BaseContentWizard
{
this.content = content;
}
-
+
public List getCreateTemplateTypes()
{
Collection ttl = TemplatingService.getInstance().getTemplateTypes();
@@ -225,7 +225,7 @@ public class CreateContentWizard extends BaseContentWizard
return this.createMimeTypes;
}
-
+
public String getTemplateTypeName()
{
return this.templateTypeName;
diff --git a/source/java/org/alfresco/web/bean/dashboard/DashboardManager.java b/source/java/org/alfresco/web/bean/dashboard/DashboardManager.java
index bea7e5f967..29e9f1de4b 100644
--- a/source/java/org/alfresco/web/bean/dashboard/DashboardManager.java
+++ b/source/java/org/alfresco/web/bean/dashboard/DashboardManager.java
@@ -42,8 +42,9 @@ public class DashboardManager
private static Log logger = LogFactory.getLog(DashboardManager.class);
private static final String PREF_DASHBOARD = "dashboard";
- static final String LAYOUT_DEFAULT = "default";
- static final String DASHLET_DEFAULT = "getting-started";
+ private static final String LAYOUT_DEFAULT = "default";
+ private static final String DASHLET_STARTEDDEFAULT = "getting-started";
+ private static final String DASHLET_TASKSDEFAULT = "tasks-todo";
private static final String JSP_DUMMY = "/jsp/dashboards/dummy.jsp";
@@ -150,13 +151,22 @@ public class DashboardManager
{
Page page = new Page("default", layout);
Column defaultColumn = new Column();
- DashletDefinition dashlet = config.getDashletDefinition(DASHLET_DEFAULT);
+
+ // add the default dashlet(s) to the column
+ DashletDefinition dashlet = config.getDashletDefinition(DASHLET_STARTEDDEFAULT);
if (dashlet != null)
{
defaultColumn.addDashlet(dashlet);
- page.addColumn(defaultColumn);
- pageConfig.addPage(page);
}
+ dashlet = config.getDashletDefinition(DASHLET_TASKSDEFAULT);
+ if (dashlet != null)
+ {
+ defaultColumn.addDashlet(dashlet);
+ }
+
+ // add the column to the page and we are done
+ page.addColumn(defaultColumn);
+ pageConfig.addPage(page);
}
}
diff --git a/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java b/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java
index 3e79a173dc..c8e5d0a086 100644
--- a/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java
+++ b/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java
@@ -447,6 +447,17 @@ public class StartWorkflowWizard extends BaseWizardBean
new String[] {workflowName});
}
+ /**
+ * Determines whether there are any workflows to start
+ * @return
+ */
+ public boolean getHasStartableWorkflows()
+ {
+ // get the list of startable workflow, this will intialise the list if necessary
+ List workflows = getStartableWorkflows();
+ return (workflows.size() > 0);
+ }
+
/**
* Returns a list of workflows that can be started.
*
diff --git a/source/java/org/alfresco/web/ui/common/renderer/ImagePickerRadioRenderer.java b/source/java/org/alfresco/web/ui/common/renderer/ImagePickerRadioRenderer.java
index e3212a7212..68fc6bb62f 100644
--- a/source/java/org/alfresco/web/ui/common/renderer/ImagePickerRadioRenderer.java
+++ b/source/java/org/alfresco/web/ui/common/renderer/ImagePickerRadioRenderer.java
@@ -25,6 +25,7 @@ import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
+import javax.faces.el.PropertyNotFoundException;
import org.alfresco.config.Config;
import org.alfresco.config.ConfigElement;
@@ -162,34 +163,46 @@ public class ImagePickerRadioRenderer extends BaseRenderer
}
else
{
- // get the child components
- for (Iterator i = imagePicker.getChildren().iterator(); i.hasNext(); /**/)
+ try
{
- UIComponent child = (UIComponent)i.next();
- if (child instanceof UIListItems)
+ // get the child components
+ for (Iterator i = imagePicker.getChildren().iterator(); i.hasNext(); /**/)
{
- // get the value of the list items component and iterate
- // through it's collection
- Object listItems = ((UIListItems)child).getValue();
- if (listItems instanceof Collection)
+ UIComponent child = (UIComponent)i.next();
+ if (child instanceof UIListItems)
{
- Iterator iter = ((Collection)listItems).iterator();
- while (iter.hasNext())
+ // get the value of the list items component and iterate
+ // through it's collection
+ Object listItems = ((UIListItems)child).getValue();
+ if (listItems instanceof Collection)
{
- UIListItem item = (UIListItem)iter.next();
- if (item.isRendered())
+ Iterator iter = ((Collection)listItems).iterator();
+ while (iter.hasNext())
{
- renderItem(context, out, imagePicker, item, onclick);
+ UIListItem item = (UIListItem)iter.next();
+ if (item.isRendered())
+ {
+ renderItem(context, out, imagePicker, item, onclick);
+ }
}
}
}
+ else if (child instanceof UIListItem && child.isRendered() == true)
+ {
+ // found a valid UIListItem child to render
+ UIListItem item = (UIListItem)child;
+ renderItem(context, out, imagePicker, item, onclick);
+ }
}
- else if (child instanceof UIListItem && child.isRendered() == true)
- {
- // found a valid UIListItem child to render
- UIListItem item = (UIListItem)child;
- renderItem(context, out, imagePicker, item, onclick);
- }
+ }
+ catch (PropertyNotFoundException pnfe)
+ {
+ // handle the scenario where the bean does not have the
+ // method specified in the value binding expression
+ if (logger.isWarnEnabled())
+ logger.warn("Failed to retrieve icons: " + pnfe.toString());
+
+ out.write(Application.getMessage(context, "no_icons_found"));
}
}
diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml
index 67c90a40f8..f5b4cd795f 100644
--- a/source/web/WEB-INF/faces-config-beans.xml
+++ b/source/web/WEB-INF/faces-config-beans.xml
@@ -1466,6 +1466,10 @@
fileFolderService
#{FileFolderService}
+
+ searchService
+ #{SearchService}
+
navigator
#{NavigationBean}
@@ -1780,43 +1784,6 @@
-
-
- The bean that backs up the Delete Post Dialog
-
- DeletePostDialog
- org.alfresco.web.bean.forums.DeletePostDialog
- session
-
- nodeService
- #{NodeService}
-
-
- fileFolderService
- #{FileFolderService}
-
-
- searchService
- #{SearchService}
-
-
- navigator
- #{NavigationBean}
-
-
- browseBean
- #{BrowseBean}
-
-
- dictionaryService
- #{DictionaryService}
-
-
- namespaceService
- #{NamespaceService}
-
-
-
The bean that holds state for the Manage Deleted Items screen.
@@ -1837,8 +1804,8 @@
#{SearchService}
- namespaceService
- #{NamespaceService}
+ dictionaryService
+ #{DictionaryService}
@@ -2352,7 +2319,7 @@
#{ContentService}
-
+
Bean that returns information on a node
diff --git a/source/web/WEB-INF/faces-config-navigation.xml b/source/web/WEB-INF/faces-config-navigation.xml
index 60e54eee7a..94494c409a 100644
--- a/source/web/WEB-INF/faces-config-navigation.xml
+++ b/source/web/WEB-INF/faces-config-navigation.xml
@@ -1,942 +1,910 @@
-
-
-
-
-
-
-
-
-
- The decision rule used by the NavigationHandler to
- determine which view must be displayed after the
- current view, login.jsp is processed.
-
- /jsp/login.jsp
-
-
- Indicates to the NavigationHandler that the browse.jsp
- view must be displayed if the Action referenced by a
- UICommand component on the login.jsp view returns
- the outcome "success".
-
- success
- /jsp/browse/browse.jsp
-
-
-
-
-
- /jsp/*
-
- browse
- /jsp/browse/browse.jsp
-
-
- myalfresco
- /jsp/dashboards/container.jsp
-
-
- about
- /jsp/dialog/about.jsp
-
-
-
-
-
- /jsp/*
-
- showDocDetails
- /jsp/dialog/document-details.jsp
-
-
- showSpaceDetails
- /jsp/dialog/space-details.jsp
-
-
- dashboard
- /jsp/browse/dashboard.jsp
-
-
- addContent
- /jsp/content/add-content-dialog.jsp
-
-
-
-
-
- /jsp/*
-
- advSearch
- /jsp/dialog/advanced-search.jsp
-
-
-
-
-
- /jsp/*
-
- logout
- /jsp/login.jsp
-
-
- relogin
- /jsp/relogin.jsp
-
-
-
-
-
- /jsp/*
-
- adminConsole
- /jsp/admin/admin-console.jsp
-
-
- userConsole
- /jsp/users/user-console.jsp
-
-
-
-
-
- /jsp/browse/browse.jsp
-
- addContent
- /jsp/content/add-content-dialog.jsp
-
-
-
- checkoutFile
- /jsp/dialog/checkout-file.jsp
-
-
- checkinFile
- /jsp/dialog/checkin-file.jsp
-
-
- undoCheckoutFile
- /jsp/dialog/undocheckout-file.jsp
-
-
- updateFile
- /jsp/dialog/update-file.jsp
-
-
- editFile
- /jsp/dialog/edit-file.jsp
-
-
- editHtmlInline
- /jsp/dialog/edit-html-inline.jsp
-
-
- editTextInline
- /jsp/dialog/edit-text-inline.jsp
-
-
- editXmlInline
- /jsp/dialog/edit-xml-inline.jsp
-
-
- manageInvitedUsers
- /jsp/roles/manage-invited-users.jsp
-
-
- manageContentUsers
- /jsp/roles/manage-content-users.jsp
-
-
- manageRules
- /jsp/dialog/rules.jsp
-
-
- previewContent
- /jsp/dialog/preview-file.jsp
-
-
- previewSpace
- /jsp/dialog/preview-space.jsp
-
-
- startDiscussion
- /jsp/forums/create-topic.jsp
-
-
- showForum
- /jsp/forums/forum.jsp
-
-
- showTopic
- /jsp/forums/topic.jsp
-
-
- saveNewSearch
- /jsp/dialog/save-search.jsp
-
-
- saveEditSearch
- /jsp/dialog/edit-search.jsp
-
-
- manageDeletedItems
- /jsp/trashcan/trash-list.jsp
-
-
-
-
- /jsp/content/add-content-dialog.jsp
-
- cancel
- /jsp/browse/browse.jsp
-
-
-
-
-
- /jsp/admin/admin-console.jsp
-
- manageCategories
- /jsp/categories/categories.jsp
-
-
- manageUsers
- /jsp/users/users.jsp
-
-
- manageGroups
- /jsp/groups/groups.jsp
-
-
- showSystemInfo
- /jsp/dialog/system-info.jsp
-
-
- showNodeBrowser
- /jsp/admin/store-browser.jsp
-
-
- import
- /jsp/dialog/import.jsp
-
-
- export
- /jsp/dialog/export.jsp
-
-
-
-
- /jsp/dialog/edit-file.jsp
-
- checkoutFile
- /jsp/dialog/checkout-file.jsp
-
-
-
-
- /jsp/dialog/edit-text-inline.jsp
-
- checkoutFile
- /jsp/dialog/checkout-file.jsp
-
-
-
-
- /jsp/dialog/edit-html-inline.jsp
-
- checkoutFile
- /jsp/dialog/checkout-file.jsp
-
-
-
-
- /jsp/dialog/edit-xml-inline.jsp
-
- checkoutFile
- /jsp/dialog/checkout-file.jsp
-
-
-
-
- /jsp/dialog/checkout-file.jsp
-
- checkoutFileLink
- /jsp/dialog/checkout-file-link.jsp
-
-
-
-
- /jsp/dialog/space-details.jsp
-
- manageInvitedUsers
- /jsp/roles/manage-invited-users.jsp
-
-
- manageRules
- /jsp/dialog/rules.jsp
-
-
- import
- /jsp/dialog/import.jsp
-
-
- export
- /jsp/dialog/export.jsp
-
-
- applyTemplate
- /jsp/dialog/apply-space-template.jsp
-
-
- applyRSSTemplate
- /jsp/dialog/apply-rss-template.jsp
-
-
- previewSpace
- /jsp/dialog/preview-space.jsp
-
-
- showForum
- /jsp/forums/forum.jsp
-
-
- editCategories
- /jsp/dialog/edit-space-category.jsp
-
-
-
-
- /jsp/dialog/apply-rss-template.jsp
-
- manageInvitedUsers
- /jsp/roles/manage-invited-users.jsp
-
-
-
-
- /jsp/dialog/document-details.jsp
-
- checkoutFile
- /jsp/dialog/checkout-file.jsp
-
-
- checkinFile
- /jsp/dialog/checkin-file.jsp
-
-
- undoCheckoutFile
- /jsp/dialog/undocheckout-file.jsp
-
-
- updateFile
- /jsp/dialog/update-file.jsp
-
-
- editFile
- /jsp/dialog/edit-file.jsp
-
-
- editHtmlInline
- /jsp/dialog/edit-html-inline.jsp
-
-
- editTextInline
- /jsp/dialog/edit-text-inline.jsp
-
-
- editXmlInline
- /jsp/dialog/edit-xml-inline.jsp
-
-
- editSimpleWorkflow
- /jsp/dialog/edit-simple-workflow.jsp
-
-
- editCategories
- /jsp/dialog/edit-category.jsp
-
-
- previewContent
- /jsp/dialog/preview-file.jsp
-
-
- showForum
- /jsp/forums/forum.jsp
-
-
- manageContentUsers
- /jsp/roles/manage-content-users.jsp
-
-
- applyTemplate
- /jsp/dialog/apply-doc-template.jsp
-
-
-
-
- /jsp/dialog/edit-simple-workflow.jsp
-
- cancel
- /jsp/dialog/document-details.jsp
-
-
- finish
- /jsp/dialog/document-details.jsp
-
-
-
-
- /jsp/dialog/edit-category.jsp
-
- cancel
- /jsp/dialog/document-details.jsp
-
-
- finish
- /jsp/dialog/document-details.jsp
-
-
-
-
- /jsp/dialog/edit-space-category.jsp
-
- cancel
- /jsp/dialog/space-details.jsp
-
-
- finish
- /jsp/dialog/space-details.jsp
-
-
-
-
- /jsp/dialog/rules.jsp
-
- deleteRule
- /jsp/dialog/delete-rule.jsp
-
-
-
-
- /jsp/dialog/delete-rule.jsp
-
- manageRules
- /jsp/dialog/rules.jsp
-
-
- cancel
- /jsp/dialog/rules.jsp
-
-
- browse
- /jsp/dialog/rules.jsp
-
-
-
-
-
- /jsp/dialog/filelink-details.jsp
-
- editLinkProperties
- /jsp/dialog/edit-link-properties.jsp
-
-
- manageContentUsers
- /jsp/roles/manage-content-users.jsp
-
-
-
-
-
- /jsp/dialog/spacelink-details.jsp
-
- editLinkProperties
- /jsp/dialog/edit-link-properties.jsp
-
-
- manageContentUsers
- /jsp/roles/manage-content-users.jsp
-
-
-
-
-
- /jsp/dialog/edit-link-properties.jsp
-
- cancelEdit
- /jsp/dialog/filelink-details.jsp
-
-
- finishEdit
- /jsp/dialog/filelink-details.jsp
-
-
-
-
-
- /jsp/roles/manage-invited-users.jsp
-
- inviteUsers
- /jsp/wizard/invite-users/invite.jsp
-
-
- editRoles
- /jsp/roles/edit-user-roles.jsp
-
-
- removeUser
- /jsp/roles/remove-invited-user.jsp
-
-
-
-
- /jsp/roles/edit-user-roles.jsp
-
- cancel
- /jsp/roles/manage-invited-users.jsp
-
-
- finish
- /jsp/roles/manage-invited-users.jsp
-
-
-
-
- /jsp/roles/remove-invited-user.jsp
-
- cancel
- /jsp/roles/manage-invited-users.jsp
-
-
- finish
- /jsp/roles/manage-invited-users.jsp
-
-
-
-
- /jsp/roles/manage-content-users.jsp
-
- inviteUsers
- /jsp/wizard/invite-content-users/invite.jsp
-
-
- editRoles
- /jsp/roles/edit-content-user-roles.jsp
-
-
- removeUser
- /jsp/roles/remove-content-user.jsp
-
-
-
-
- /jsp/roles/edit-content-user-roles.jsp
-
- cancel
- /jsp/roles/manage-content-users.jsp
-
-
- finish
- /jsp/roles/manage-content-users.jsp
-
-
-
-
- /jsp/roles/remove-content-user.jsp
-
- cancel
- /jsp/roles/manage-content-users.jsp
-
-
- finish
- /jsp/roles/manage-content-users.jsp
-
-
-
-
-
- /jsp/wizard/invite-users/*
-
- invite
- /jsp/wizard/invite-users/invite.jsp
-
-
- notify
- /jsp/wizard/invite-users/notify.jsp
-
-
- cancel
- /jsp/roles/manage-invited-users.jsp
-
-
- finish
- /jsp/roles/manage-invited-users.jsp
-
-
-
-
-
- /jsp/wizard/invite-content-users/*
-
- invite
- /jsp/wizard/invite-content-users/invite.jsp
-
-
- notify
- /jsp/wizard/invite-content-users/notify.jsp
-
-
- cancel
- /jsp/roles/manage-content-users.jsp
-
-
- finish
- /jsp/roles/manage-content-users.jsp
-
-
-
-
-
- /jsp/users/*
-
- manageUsers
- /jsp/users/users.jsp
-
-
- cancel
- /jsp/users/users.jsp
-
-
-
-
- /jsp/users/users.jsp
-
- createUser
- /jsp/wizard/new-user/person-properties.jsp
-
-
- editUser
- /jsp/wizard/new-user/person-properties.jsp
-
-
- deleteUser
- /jsp/users/delete-user.jsp
-
-
- changePassword
- /jsp/users/change-password.jsp
-
-
-
-
-
- /jsp/users/user-console.jsp
-
- changePassword
- /jsp/users/change-my-password.jsp
-
-
- editUserDetails
- /jsp/users/edit-user-details.jsp
-
-
-
-
-
- /jsp/wizard/new-user/*
-
- cancel
- /jsp/users/users.jsp
-
-
- finish
- /jsp/users/users.jsp
-
-
- person-properties
- /jsp/wizard/new-user/person-properties.jsp
-
-
- user-properties
- /jsp/wizard/new-user/user-properties.jsp
-
-
- summary
- /jsp/wizard/new-user/summary.jsp
-
-
-
-
-
- /jsp/groups/*
-
- newGroup
- /jsp/groups/new-group.jsp
-
-
- deleteGroup
- /jsp/groups/delete-group.jsp
-
-
- addUser
- /jsp/groups/add-user.jsp
-
-
- deleteUser
- /jsp/groups/delete-user.jsp
-
-
- finish
- /jsp/groups/groups.jsp
-
-
- cancel
- /jsp/groups/groups.jsp
-
-
-
-
-
- /jsp/categories/*
-
- addCategory
- /jsp/categories/new-category.jsp
-
-
- editCategory
- /jsp/categories/edit-category.jsp
-
-
- deleteCategory
- /jsp/categories/delete-category.jsp
-
-
- finish
- /jsp/categories/categories.jsp
-
-
- cancel
- /jsp/categories/categories.jsp
-
-
-
-
-
- /jsp/wizard/*
-
- cancel
- /jsp/browse/browse.jsp
-
-
- finish
- /jsp/browse/browse.jsp
-
-
-
-
-
- /jsp/admin/*
-
- #{AdminNodeBrowseBean.selectStores}
- success
- /jsp/admin/store-browser.jsp
-
-
- nodeBrowser
- /jsp/admin/node-browser.jsp
-
-
-
-
- /jsp/admin/store-browser.jsp
-
- #{AdminNodeBrowseBean.selectStore}
- success
- /jsp/admin/node-browser.jsp
-
-
-
-
- /jsp/admin/node-browser.jsp
-
- #{AdminNodeBrowseBean.selectChild}
- success
- /jsp/admin/node-browser.jsp
-
-
- #{AdminNodeBrowseBean.selectPrimaryPath}
- success
- /jsp/admin/node-browser.jsp
-
-
- #{AdminNodeBrowseBean.selectPrimaryParent}
- success
- /jsp/admin/node-browser.jsp
-
-
- #{AdminNodeBrowseBean.selectParent}
- success
- /jsp/admin/node-browser.jsp
-
-
- #{AdminNodeBrowseBean.selectToNode}
- success
- /jsp/admin/node-browser.jsp
-
-
- #{AdminNodeBrowseBean.selectNodeProperty}
- success
- /jsp/admin/node-browser.jsp
-
-
- #{AdminNodeBrowseBean.submitSearch}
- error
- /jsp/admin/node-browser.jsp
-
-
- #{AdminNodeBrowseBean.submitSearch}
- node
- /jsp/admin/node-browser.jsp
-
-
- #{AdminNodeBrowseBean.submitSearch}
- search
- /jsp/admin/search-results.jsp
-
-
-
-
- /jsp/admin/search-results.jsp
-
- #{AdminNodeBrowseBean.selectResultNode}
- success
- /jsp/admin/node-browser.jsp
-
-
-
-
-
- /jsp/forums/*
-
-
-
- showForumsDetails
- /jsp/forums/forums-details.jsp
-
-
- showForumDetails
- /jsp/forums/forum-details.jsp
-
-
- showTopicDetails
- /jsp/forums/topic-details.jsp
-
-
- manageInvitedUsers
- /jsp/roles/manage-invited-users.jsp
-
-
- import
- /jsp/dialog/import.jsp
-
-
- export
- /jsp/dialog/export.jsp
-
-
-
-
-
- /jsp/trashcan/*
-
- deleteItem
- /jsp/trashcan/delete-item.jsp
-
-
- recoverItem
- /jsp/trashcan/recover-item.jsp
-
-
- recoverAllItems
- /jsp/trashcan/recover-all.jsp
-
-
- deleteAllItems
- /jsp/trashcan/delete-all.jsp
-
-
- recoverListedItems
- /jsp/trashcan/recover-listed.jsp
-
-
- deleteListedItems
- /jsp/trashcan/delete-listed.jsp
-
-
- itemDetails
- /jsp/trashcan/item-details.jsp
-
-
- recoveryReport
- /jsp/trashcan/recovery-report.jsp
-
-
-
-
- /jsp/dialog/container.jsp
-
-
-
- forumsDeleted
- /jsp/forums/forums.jsp
-
-
- forumDeleted
- /jsp/forums/forums.jsp
-
-
- topicDeleted
- /jsp/forums/forum.jsp
-
-
-
-
-
- checkoutFile
- /jsp/dialog/checkout-file.jsp
-
-
- checkinFile
- /jsp/dialog/checkin-file.jsp
-
-
- undoCheckoutFile
- /jsp/dialog/undocheckout-file.jsp
-
-
- updateFile
- /jsp/dialog/update-file.jsp
-
-
- editFile
- /jsp/dialog/edit-file.jsp
-
-
- editHtmlInline
- /jsp/dialog/edit-html-inline.jsp
-
-
- editTextInline
- /jsp/dialog/edit-text-inline.jsp
-
-
- itemDetails
- /jsp/trashcan/item-details.jsp
-
-
- recoveryReport
- /jsp/trashcan/recovery-report.jsp
-
-
-
-
+
+
+
+
+
+
+
+
+
+ The decision rule used by the NavigationHandler to
+ determine which view must be displayed after the
+ current view, login.jsp is processed.
+
+ /jsp/login.jsp
+
+
+ Indicates to the NavigationHandler that the browse.jsp
+ view must be displayed if the Action referenced by a
+ UICommand component on the login.jsp view returns
+ the outcome "success".
+
+ success
+ /jsp/browse/browse.jsp
+
+
+
+
+
+ /jsp/*
+
+ browse
+ /jsp/browse/browse.jsp
+
+
+ myalfresco
+ /jsp/dashboards/container.jsp
+
+
+ about
+ /jsp/dialog/about.jsp
+
+
+
+
+
+ /jsp/*
+
+ showDocDetails
+ /jsp/dialog/document-details.jsp
+
+
+ showSpaceDetails
+ /jsp/dialog/space-details.jsp
+
+
+ dashboard
+ /jsp/browse/dashboard.jsp
+
+
+ addContent
+ /jsp/content/add-content-dialog.jsp
+
+
+
+
+
+ /jsp/*
+
+ advSearch
+ /jsp/dialog/advanced-search.jsp
+
+
+
+
+
+ /jsp/*
+
+ logout
+ /jsp/login.jsp
+
+
+ relogin
+ /jsp/relogin.jsp
+
+
+
+
+
+ /jsp/*
+
+ adminConsole
+ /jsp/admin/admin-console.jsp
+
+
+ userConsole
+ /jsp/users/user-console.jsp
+
+
+
+
+
+ /jsp/*
+
+ addContent
+ /jsp/content/add-content-dialog.jsp
+
+
+
+ checkoutFile
+ /jsp/dialog/checkout-file.jsp
+
+
+ checkinFile
+ /jsp/dialog/checkin-file.jsp
+
+
+ undoCheckoutFile
+ /jsp/dialog/undocheckout-file.jsp
+
+
+ updateFile
+ /jsp/dialog/update-file.jsp
+
+
+ editFile
+ /jsp/dialog/edit-file.jsp
+
+
+ editHtmlInline
+ /jsp/dialog/edit-html-inline.jsp
+
+
+ editTextInline
+ /jsp/dialog/edit-text-inline.jsp
+
+
+
+
+
+ /jsp/browse/browse.jsp
+
+
+
+ editXmlInline
+ /jsp/dialog/edit-xml-inline.jsp
+
+
+ manageInvitedUsers
+ /jsp/roles/manage-invited-users.jsp
+
+
+ manageContentUsers
+ /jsp/roles/manage-content-users.jsp
+
+
+ manageRules
+ /jsp/dialog/rules.jsp
+
+
+ previewContent
+ /jsp/dialog/preview-file.jsp
+
+
+ previewSpace
+ /jsp/dialog/preview-space.jsp
+
+
+ startDiscussion
+ /jsp/forums/create-topic.jsp
+
+
+ showForum
+ /jsp/forums/forum.jsp
+
+
+ showTopic
+ /jsp/forums/topic.jsp
+
+
+ saveNewSearch
+ /jsp/dialog/save-search.jsp
+
+
+ saveEditSearch
+ /jsp/dialog/edit-search.jsp
+
+
+ manageDeletedItems
+ /jsp/trashcan/trash-list.jsp
+
+
+
+
+ /jsp/content/add-content-dialog.jsp
+
+ cancel
+ /jsp/browse/browse.jsp
+
+
+
+
+
+ /jsp/admin/admin-console.jsp
+
+ manageCategories
+ /jsp/categories/categories.jsp
+
+
+ manageUsers
+ /jsp/users/users.jsp
+
+
+ manageGroups
+ /jsp/groups/groups.jsp
+
+
+ showSystemInfo
+ /jsp/dialog/system-info.jsp
+
+
+ showNodeBrowser
+ /jsp/admin/store-browser.jsp
+
+
+ import
+ /jsp/dialog/import.jsp
+
+
+ export
+ /jsp/dialog/export.jsp
+
+
+
+
+ /jsp/dialog/edit-file.jsp
+
+ checkoutFile
+ /jsp/dialog/checkout-file.jsp
+
+
+
+
+ /jsp/dialog/edit-text-inline.jsp
+
+ checkoutFile
+ /jsp/dialog/checkout-file.jsp
+
+
+
+
+ /jsp/dialog/edit-html-inline.jsp
+
+ checkoutFile
+ /jsp/dialog/checkout-file.jsp
+
+
+
+
+ /jsp/dialog/edit-xml-inline.jsp
+
+ checkoutFile
+ /jsp/dialog/checkout-file.jsp
+
+
+
+
+ /jsp/dialog/checkout-file.jsp
+
+ checkoutFileLink
+ /jsp/dialog/checkout-file-link.jsp
+
+
+
+
+ /jsp/dialog/space-details.jsp
+
+ manageInvitedUsers
+ /jsp/roles/manage-invited-users.jsp
+
+
+ manageRules
+ /jsp/dialog/rules.jsp
+
+
+ import
+ /jsp/dialog/import.jsp
+
+
+ export
+ /jsp/dialog/export.jsp
+
+
+ applyTemplate
+ /jsp/dialog/apply-space-template.jsp
+
+
+ applyRSSTemplate
+ /jsp/dialog/apply-rss-template.jsp
+
+
+ previewSpace
+ /jsp/dialog/preview-space.jsp
+
+
+ showForum
+ /jsp/forums/forum.jsp
+
+
+ editCategories
+ /jsp/dialog/edit-space-category.jsp
+
+
+
+
+ /jsp/dialog/apply-rss-template.jsp
+
+ manageInvitedUsers
+ /jsp/roles/manage-invited-users.jsp
+
+
+
+
+ /jsp/dialog/document-details.jsp
+
+ checkoutFile
+ /jsp/dialog/checkout-file.jsp
+
+
+ checkinFile
+ /jsp/dialog/checkin-file.jsp
+
+
+ undoCheckoutFile
+ /jsp/dialog/undocheckout-file.jsp
+
+
+ updateFile
+ /jsp/dialog/update-file.jsp
+
+
+ editFile
+ /jsp/dialog/edit-file.jsp
+
+
+ editHtmlInline
+ /jsp/dialog/edit-html-inline.jsp
+
+
+ editTextInline
+ /jsp/dialog/edit-text-inline.jsp
+
+
+ editXmlInline
+ /jsp/dialog/edit-xml-inline.jsp
+
+
+ editSimpleWorkflow
+ /jsp/dialog/edit-simple-workflow.jsp
+
+
+ editCategories
+ /jsp/dialog/edit-category.jsp
+
+
+ previewContent
+ /jsp/dialog/preview-file.jsp
+
+
+ showForum
+ /jsp/forums/forum.jsp
+
+
+ manageContentUsers
+ /jsp/roles/manage-content-users.jsp
+
+
+ applyTemplate
+ /jsp/dialog/apply-doc-template.jsp
+
+
+
+
+ /jsp/dialog/edit-simple-workflow.jsp
+
+ cancel
+ /jsp/dialog/document-details.jsp
+
+
+ finish
+ /jsp/dialog/document-details.jsp
+
+
+
+
+ /jsp/dialog/edit-category.jsp
+
+ cancel
+ /jsp/dialog/document-details.jsp
+
+
+ finish
+ /jsp/dialog/document-details.jsp
+
+
+
+
+ /jsp/dialog/edit-space-category.jsp
+
+ cancel
+ /jsp/dialog/space-details.jsp
+
+
+ finish
+ /jsp/dialog/space-details.jsp
+
+
+
+
+ /jsp/dialog/rules.jsp
+
+ deleteRule
+ /jsp/dialog/delete-rule.jsp
+
+
+
+
+ /jsp/dialog/delete-rule.jsp
+
+ manageRules
+ /jsp/dialog/rules.jsp
+
+
+ cancel
+ /jsp/dialog/rules.jsp
+
+
+ browse
+ /jsp/dialog/rules.jsp
+
+
+
+
+
+ /jsp/dialog/filelink-details.jsp
+
+ editLinkProperties
+ /jsp/dialog/edit-link-properties.jsp
+
+
+ manageContentUsers
+ /jsp/roles/manage-content-users.jsp
+
+
+
+
+
+ /jsp/dialog/spacelink-details.jsp
+
+ editLinkProperties
+ /jsp/dialog/edit-link-properties.jsp
+
+
+ manageContentUsers
+ /jsp/roles/manage-content-users.jsp
+
+
+
+
+
+ /jsp/dialog/edit-link-properties.jsp
+
+ cancelEdit
+ /jsp/dialog/filelink-details.jsp
+
+
+ finishEdit
+ /jsp/dialog/filelink-details.jsp
+
+
+
+
+
+ /jsp/roles/manage-invited-users.jsp
+
+ inviteUsers
+ /jsp/wizard/invite-users/invite.jsp
+
+
+ editRoles
+ /jsp/roles/edit-user-roles.jsp
+
+
+ removeUser
+ /jsp/roles/remove-invited-user.jsp
+
+
+
+
+ /jsp/roles/edit-user-roles.jsp
+
+ cancel
+ /jsp/roles/manage-invited-users.jsp
+
+
+ finish
+ /jsp/roles/manage-invited-users.jsp
+
+
+
+
+ /jsp/roles/remove-invited-user.jsp
+
+ cancel
+ /jsp/roles/manage-invited-users.jsp
+
+
+ finish
+ /jsp/roles/manage-invited-users.jsp
+
+
+
+
+ /jsp/roles/manage-content-users.jsp
+
+ inviteUsers
+ /jsp/wizard/invite-content-users/invite.jsp
+
+
+ editRoles
+ /jsp/roles/edit-content-user-roles.jsp
+
+
+ removeUser
+ /jsp/roles/remove-content-user.jsp
+
+
+
+
+ /jsp/roles/edit-content-user-roles.jsp
+
+ cancel
+ /jsp/roles/manage-content-users.jsp
+
+
+ finish
+ /jsp/roles/manage-content-users.jsp
+
+
+
+
+ /jsp/roles/remove-content-user.jsp
+
+ cancel
+ /jsp/roles/manage-content-users.jsp
+
+
+ finish
+ /jsp/roles/manage-content-users.jsp
+
+
+
+
+
+ /jsp/wizard/invite-users/*
+
+ invite
+ /jsp/wizard/invite-users/invite.jsp
+
+
+ notify
+ /jsp/wizard/invite-users/notify.jsp
+
+
+ cancel
+ /jsp/roles/manage-invited-users.jsp
+
+
+ finish
+ /jsp/roles/manage-invited-users.jsp
+
+
+
+
+
+ /jsp/wizard/invite-content-users/*
+
+ invite
+ /jsp/wizard/invite-content-users/invite.jsp
+
+
+ notify
+ /jsp/wizard/invite-content-users/notify.jsp
+
+
+ cancel
+ /jsp/roles/manage-content-users.jsp
+
+
+ finish
+ /jsp/roles/manage-content-users.jsp
+
+
+
+
+
+ /jsp/users/*
+
+ manageUsers
+ /jsp/users/users.jsp
+
+
+ cancel
+ /jsp/users/users.jsp
+
+
+
+
+ /jsp/users/users.jsp
+
+ createUser
+ /jsp/wizard/new-user/person-properties.jsp
+
+
+ editUser
+ /jsp/wizard/new-user/person-properties.jsp
+
+
+ deleteUser
+ /jsp/users/delete-user.jsp
+
+
+ changePassword
+ /jsp/users/change-password.jsp
+
+
+
+
+
+ /jsp/users/user-console.jsp
+
+ changePassword
+ /jsp/users/change-my-password.jsp
+
+
+ editUserDetails
+ /jsp/users/edit-user-details.jsp
+
+
+
+
+
+ /jsp/wizard/new-user/*
+
+ cancel
+ /jsp/users/users.jsp
+
+
+ finish
+ /jsp/users/users.jsp
+
+
+ person-properties
+ /jsp/wizard/new-user/person-properties.jsp
+
+
+ user-properties
+ /jsp/wizard/new-user/user-properties.jsp
+
+
+ summary
+ /jsp/wizard/new-user/summary.jsp
+
+
+
+
+
+ /jsp/groups/*
+
+ newGroup
+ /jsp/groups/new-group.jsp
+
+
+ deleteGroup
+ /jsp/groups/delete-group.jsp
+
+
+ addUser
+ /jsp/groups/add-user.jsp
+
+
+ deleteUser
+ /jsp/groups/delete-user.jsp
+
+
+ finish
+ /jsp/groups/groups.jsp
+
+
+ cancel
+ /jsp/groups/groups.jsp
+
+
+
+
+
+ /jsp/categories/*
+
+ addCategory
+ /jsp/categories/new-category.jsp
+
+
+ editCategory
+ /jsp/categories/edit-category.jsp
+
+
+ deleteCategory
+ /jsp/categories/delete-category.jsp
+
+
+ finish
+ /jsp/categories/categories.jsp
+
+
+ cancel
+ /jsp/categories/categories.jsp
+
+
+
+
+
+ /jsp/wizard/*
+
+ cancel
+ /jsp/browse/browse.jsp
+
+
+ finish
+ /jsp/browse/browse.jsp
+
+
+
+
+
+ /jsp/admin/*
+
+ #{AdminNodeBrowseBean.selectStores}
+ success
+ /jsp/admin/store-browser.jsp
+
+
+ nodeBrowser
+ /jsp/admin/node-browser.jsp
+
+
+
+
+ /jsp/admin/store-browser.jsp
+
+ #{AdminNodeBrowseBean.selectStore}
+ success
+ /jsp/admin/node-browser.jsp
+
+
+
+
+ /jsp/admin/node-browser.jsp
+
+ #{AdminNodeBrowseBean.selectChild}
+ success
+ /jsp/admin/node-browser.jsp
+
+
+ #{AdminNodeBrowseBean.selectPrimaryPath}
+ success
+ /jsp/admin/node-browser.jsp
+
+
+ #{AdminNodeBrowseBean.selectPrimaryParent}
+ success
+ /jsp/admin/node-browser.jsp
+
+
+ #{AdminNodeBrowseBean.selectParent}
+ success
+ /jsp/admin/node-browser.jsp
+
+
+ #{AdminNodeBrowseBean.selectToNode}
+ success
+ /jsp/admin/node-browser.jsp
+
+
+ #{AdminNodeBrowseBean.selectNodeProperty}
+ success
+ /jsp/admin/node-browser.jsp
+
+
+ #{AdminNodeBrowseBean.submitSearch}
+ error
+ /jsp/admin/node-browser.jsp
+
+
+ #{AdminNodeBrowseBean.submitSearch}
+ node
+ /jsp/admin/node-browser.jsp
+
+
+ #{AdminNodeBrowseBean.submitSearch}
+ search
+ /jsp/admin/search-results.jsp
+
+
+
+
+ /jsp/admin/search-results.jsp
+
+ #{AdminNodeBrowseBean.selectResultNode}
+ success
+ /jsp/admin/node-browser.jsp
+
+
+
+
+
+ /jsp/forums/*
+
+
+
+ showForumsDetails
+ /jsp/forums/forums-details.jsp
+
+
+ showForumDetails
+ /jsp/forums/forum-details.jsp
+
+
+ showTopicDetails
+ /jsp/forums/topic-details.jsp
+
+
+ manageInvitedUsers
+ /jsp/roles/manage-invited-users.jsp
+
+
+ import
+ /jsp/dialog/import.jsp
+
+
+ export
+ /jsp/dialog/export.jsp
+
+
+
+
+
+ /jsp/trashcan/*
+
+ deleteItem
+ /jsp/trashcan/delete-item.jsp
+
+
+ recoverItem
+ /jsp/trashcan/recover-item.jsp
+
+
+ recoverAllItems
+ /jsp/trashcan/recover-all.jsp
+
+
+ deleteAllItems
+ /jsp/trashcan/delete-all.jsp
+
+
+ recoverListedItems
+ /jsp/trashcan/recover-listed.jsp
+
+
+ deleteListedItems
+ /jsp/trashcan/delete-listed.jsp
+
+
+ itemDetails
+ /jsp/trashcan/item-details.jsp
+
+
+ recoveryReport
+ /jsp/trashcan/recovery-report.jsp
+
+
+
+
+ /jsp/dialog/container.jsp
+
+
+
+ forumsDeleted
+ /jsp/forums/forums.jsp
+
+
+ forumDeleted
+ /jsp/forums/forums.jsp
+
+
+ topicDeleted
+ /jsp/forums/forum.jsp
+
+
+
+
diff --git a/source/web/css/main.css b/source/web/css/main.css
index 9e3053357c..2a6e4c1746 100644
--- a/source/web/css/main.css
+++ b/source/web/css/main.css
@@ -529,6 +529,13 @@ a.topToolbarLinkHighlight, a.topToolbarLinkHighlight:link, a.topToolbarLinkHighl
border-color: #AAAAAA;
}
+.workflowSelection
+{
+ border: 1px solid #676767;
+ background-color: #efefef;
+ padding: 6px 12px 12px 6px;
+}
+
.workflowSummary
{
margin-left: 6px;
diff --git a/source/web/images/logo/alfresco_enterprise.gif b/source/web/images/logo/alfresco_enterprise.gif
deleted file mode 100644
index f1b8240c8d..0000000000
Binary files a/source/web/images/logo/alfresco_enterprise.gif and /dev/null differ
diff --git a/source/web/jsp/browse/browse.jsp b/source/web/jsp/browse/browse.jsp
index 4314fc5948..94cc90a480 100644
--- a/source/web/jsp/browse/browse.jsp
+++ b/source/web/jsp/browse/browse.jsp
@@ -202,6 +202,21 @@
%>/images/parts/statuspanel_9.gif) |
+ <%-- Custom Template View --%>
+
+
+ |
+
+
+
+
+ |
+ |
+
+
+
<%-- Details - Spaces --%>
|
@@ -218,7 +233,8 @@
+ label="#{msg.browse_spaces}" progressive="true" facetsId="spaces-panel-facets"
+ expanded='#{BrowseBean.panels["spaces-panel"]}' expandedActionListener="#{BrowseBean.expandPanel}">
<%-- Spaces List --%>
+ label="#{msg.browse_content}" progressive="true" facetsId="content-panel-facets"
+ expanded='#{BrowseBean.panels["content-panel"]}' expandedActionListener="#{BrowseBean.expandPanel}">
<%-- Content list --%>
-
-
+
+
@@ -46,8 +46,8 @@
-
-
+
+
<%-- note this component ID is referenced in DashboardWizard --%>
@@ -55,22 +55,22 @@
-
+
-
+
-
+
<%-- note this component ID is referenced in DashboardWizard --%>
-
+
-
+
diff --git a/source/web/jsp/rules/details.jsp b/source/web/jsp/rules/details.jsp
index 1f03e9e4e1..34996610a0 100644
--- a/source/web/jsp/rules/details.jsp
+++ b/source/web/jsp/rules/details.jsp
@@ -125,5 +125,15 @@
+
+
+
+
+
+
+
+
+ |
+
\ No newline at end of file
diff --git a/source/web/jsp/workflow/manage-task-dialog.jsp b/source/web/jsp/workflow/manage-task-dialog.jsp
index 131268c079..f3816e9996 100644
--- a/source/web/jsp/workflow/manage-task-dialog.jsp
+++ b/source/web/jsp/workflow/manage-task-dialog.jsp
@@ -19,14 +19,14 @@
<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
-
-
+
@@ -38,60 +38,60 @@
initialSortColumn="name" initialSortDescending="true">
<%-- Name column --%>
-
+
-
+
-
-
-
+
+
<%-- Description column --%>
-
+
-
+
-
+
<%-- Path column --%>
-
+
-
+
-
+
<%-- Created Date column --%>
-
+
-
+
-
+
<%-- Modified Date column --%>
-
+
-
+
-
+
<%-- Actions column --%>
-
+
-
+
-
@@ -108,12 +108,14 @@
--%>
-
-
+
+
-
-
+
+
@@ -122,11 +124,11 @@
-
+
-
+
\ No newline at end of file
diff --git a/source/web/jsp/workflow/reassign-task-dialog.jsp b/source/web/jsp/workflow/reassign-task-dialog.jsp
index 0e14e13887..4a4f37b5c4 100644
--- a/source/web/jsp/workflow/reassign-task-dialog.jsp
+++ b/source/web/jsp/workflow/reassign-task-dialog.jsp
@@ -23,7 +23,7 @@
<%@ page buffer="32kb" contentType="text/html;charset=UTF-8" %>
<%@ page isELIgnored="false" %>
-
+
diff --git a/source/web/jsp/workflow/start-workflow-wizard/choose-workflow.jsp b/source/web/jsp/workflow/start-workflow-wizard/choose-workflow.jsp
index a3799bbefb..1d90b698a0 100644
--- a/source/web/jsp/workflow/start-workflow-wizard/choose-workflow.jsp
+++ b/source/web/jsp/workflow/start-workflow-wizard/choose-workflow.jsp
@@ -19,10 +19,29 @@
<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
-
+<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %>
+
+
+
+ <%PanelGenerator.generatePanelStart(out, request.getContextPath(), "yellowInner", "#ffffcc");%>
+
+ <%PanelGenerator.generatePanelEnd(out, request.getContextPath(), "yellowInner");%>
+
+
+
+
-
\ No newline at end of file
+
+
diff --git a/source/web/jsp/workflow/start-workflow-wizard/workflow-options.jsp b/source/web/jsp/workflow/start-workflow-wizard/workflow-options.jsp
index 4e2b0af400..ca5e0873d8 100644
--- a/source/web/jsp/workflow/start-workflow-wizard/workflow-options.jsp
+++ b/source/web/jsp/workflow/start-workflow-wizard/workflow-options.jsp
@@ -21,7 +21,7 @@
<%@ page import="org.alfresco.web.ui.common.PanelGenerator" %>
-
+
<%PanelGenerator.generatePanelStart(out, request.getContextPath(), "yellowInner", "#ffffcc");%>
@@ -37,97 +37,98 @@
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+ <%-- Name column --%>
+
+
+
+
+
+
+
+
+
+
+ <%-- Description column --%>
+
+
+
+
+
+
+
+ <%-- Path column --%>
+
+
+
+
+
+
+
+ <%-- Created Date column --%>
+
+
+
+
+
+
+
+
+
+ <%-- Modified Date column --%>
+
+
+
+
+
+
+
+
+
+ <%-- Actions column --%>
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
- <%-- Name column --%>
-
-
-
-
-
-
-
-
-
-
- <%-- Description column --%>
-
-
-
-
-
-
-
- <%-- Path column --%>
-
-
-
-
-
-
-
- <%-- Created Date column --%>
-
-
-
-
-
-
-
-
-
- <%-- Modified Date column --%>
-
-
-
-
-
-
-
-
-
- <%-- Actions column --%>
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/source/web/jsp/workflow/tasks-completed-dashlet.jsp b/source/web/jsp/workflow/tasks-completed-dashlet.jsp
index 0efb655524..8b624bc8cf 100644
--- a/source/web/jsp/workflow/tasks-completed-dashlet.jsp
+++ b/source/web/jsp/workflow/tasks-completed-dashlet.jsp
@@ -9,64 +9,64 @@
initialSortColumn="name" initialSortDescending="true">
<%-- Primary column for details view mode --%>
-
+
-
+
-
-
<%-- Task id column --%>
-
+
-
+
-
+
<%-- Source column --%>
-
+
-
+
-
+
<%-- Completed date column --%>
-
+
-
+
-
+
<%-- Outcome column --%>
-
+
-
+
-
+
<%-- Actions column --%>
-
+
-
+
-
-
+
\ No newline at end of file
diff --git a/source/web/jsp/workflow/tasks-todo-dashlet.jsp b/source/web/jsp/workflow/tasks-todo-dashlet.jsp
index ee386f5ca5..3b1b872932 100644
--- a/source/web/jsp/workflow/tasks-todo-dashlet.jsp
+++ b/source/web/jsp/workflow/tasks-todo-dashlet.jsp
@@ -9,72 +9,72 @@
initialSortColumn="name" initialSortDescending="true">
<%-- Primary column for details view mode --%>
-
+
-
+
-
-
<%-- Task id column --%>
-
+
-
+
-
+
<%-- Source column --%>
-
+
-
+
-
+
<%-- Due date column --%>
-
+
-
+
-
+
<%-- Status column --%>
-
+
-
+
-
+
<%-- Priority column --%>
-
+
-
+
-
+
<%-- Actions column --%>
-
+
-
+
-
-
+
\ No newline at end of file
diff --git a/source/web/jsp/workflow/view-completed-task-dialog.jsp b/source/web/jsp/workflow/view-completed-task-dialog.jsp
index 6287762b9c..e93db93780 100644
--- a/source/web/jsp/workflow/view-completed-task-dialog.jsp
+++ b/source/web/jsp/workflow/view-completed-task-dialog.jsp
@@ -26,7 +26,7 @@
var="taskProps" columns="1" externalConfig="true" mode="view" />
-
+
@@ -38,61 +38,61 @@
initialSortColumn="name" initialSortDescending="true">
<%-- Name column --%>
-
+
-
+
-
-
-
+
+
<%-- Description column --%>
-
+
-
+
-
+
<%-- Path column --%>
-
+
-
+
-
+
<%-- Created Date column --%>
-
+
-
+
-
+
<%-- Modified Date column --%>
-
+
-
+
-
+
-
+
-
+
|