| /******************************************************************************* |
| * Copyright (c) 2004, 2006 Sybase, Inc. and others. |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Sybase, Inc. - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jst.jsf.facesconfig.ui.pageflow.synchronization; |
| |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.Notifier; |
| import org.eclipse.emf.common.notify.impl.AdapterImpl; |
| import org.eclipse.emf.common.util.TreeIterator; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.InternalEObject; |
| import org.eclipse.emf.ecore.impl.ENotificationImpl; |
| import org.eclipse.jst.jsf.facesconfig.emf.DescriptionType; |
| import org.eclipse.jst.jsf.facesconfig.emf.DisplayNameType; |
| import org.eclipse.jst.jsf.facesconfig.emf.FacesConfigFactory; |
| import org.eclipse.jst.jsf.facesconfig.emf.FacesConfigPackage; |
| import org.eclipse.jst.jsf.facesconfig.emf.FacesConfigType; |
| import org.eclipse.jst.jsf.facesconfig.emf.FromViewIdType; |
| import org.eclipse.jst.jsf.facesconfig.emf.IconType; |
| import org.eclipse.jst.jsf.facesconfig.emf.LargeIconType; |
| import org.eclipse.jst.jsf.facesconfig.emf.NavigationCaseType; |
| import org.eclipse.jst.jsf.facesconfig.emf.NavigationRuleType; |
| import org.eclipse.jst.jsf.facesconfig.emf.SmallIconType; |
| import org.eclipse.jst.jsf.facesconfig.emf.ToViewIdType; |
| import org.eclipse.jst.jsf.facesconfig.ui.pageflow.model.Pageflow; |
| import org.eclipse.jst.jsf.facesconfig.ui.pageflow.model.PageflowElement; |
| import org.eclipse.jst.jsf.facesconfig.ui.pageflow.model.PageflowFactory; |
| import org.eclipse.jst.jsf.facesconfig.ui.pageflow.model.PageflowLink; |
| import org.eclipse.jst.jsf.facesconfig.ui.pageflow.model.PageflowNode; |
| import org.eclipse.jst.jsf.facesconfig.ui.pageflow.model.PageflowPage; |
| import org.eclipse.jst.jsf.facesconfig.ui.pageflow.model.impl.PageReferenceElement; |
| import org.eclipse.jst.jsf.facesconfig.ui.pageflow.model.impl.ReferenceElement; |
| import org.eclipse.jst.jsf.facesconfig.ui.pageflow.util.PageflowModelManager; |
| import org.eclipse.jst.jsf.facesconfig.ui.pageflow.util.PageflowTransform; |
| import org.eclipse.jst.jsf.facesconfig.ui.util.WebrootUtil; |
| |
| /** |
| * Update and synchronize pageflow from faces-config or vice-versa. |
| * |
| * @author hmeng |
| * |
| */ |
| |
| public class FC2PFTransformer extends AdapterImpl { |
| |
| // For code debug. |
| private static final boolean DEBUG = false; |
| |
| /** |
| * the first notification event type after the defaults |
| */ |
| public static final int MY_NOTIFICATION_TYPE = Notification.EVENT_TYPE_COUNT + 1; |
| |
| /** |
| * the first notification event type after MY_NOTIFICATION_TYPE |
| */ |
| public static final int MY_NOTIFICATION_TYPE1 = MY_NOTIFICATION_TYPE + 1; |
| |
| /** |
| * The listener is active. |
| */ |
| private boolean listenToNotify; |
| |
| /** |
| * Avoid redundent event. |
| */ |
| private boolean isInEvent; |
| |
| boolean pageflowChanged = false; |
| |
| /** |
| * Perform operations batched. |
| */ |
| boolean needBatchOperations = false; |
| |
| /** |
| * Catches |
| */ |
| private Map mapPaths2PF = new HashMap(); |
| |
| private Map mapCases2Links = new HashMap(); |
| |
| /** |
| * The pageflow model. |
| */ |
| private Pageflow pageflow; |
| |
| /** |
| * The faces-config model. |
| */ |
| FacesConfigType facesConfig; |
| |
| /** |
| * Default constructor |
| */ |
| public FC2PFTransformer() { |
| super(); |
| // TODO Auto-generated constructor stub |
| } |
| |
| /** |
| * @param listenToNotify |
| */ |
| public void setListenToNotify(boolean listenToNotify) { |
| this.listenToNotify = listenToNotify; |
| } |
| |
| private void postEMFChanged() { |
| startFCNotify(); |
| // Refresh all facesConfig? |
| facesConfig.eNotify(new ENotificationImpl( |
| (InternalEObject) facesConfig, Notification.REMOVE, |
| FacesConfigPackage.FACES_CONFIG_TYPE__NAVIGATION_RULE, null, |
| null)); |
| List rules; |
| rules = facesConfig.getNavigationRule(); |
| for (int i = 0; i < rules.size(); i++) { |
| ((NavigationRuleType) rules.get(i)).eNotify(new ENotificationImpl( |
| (InternalEObject) rules.get(i), Notification.REMOVE, |
| FacesConfigPackage.NAVIGATION_RULE_TYPE__NAVIGATION_CASE, |
| null, null)); |
| } |
| } |
| |
| /** |
| * Set notify adapters. |
| * |
| */ |
| private void startFCNotify() { |
| TreeIterator iterator = facesConfig.eAllContents(); |
| while (iterator.hasNext()) { |
| EObject object = (EObject) iterator.next(); |
| object.eSetDeliver(true); |
| } |
| facesConfig.eSetDeliver(true); |
| } |
| |
| /** |
| * Set not notify adapters |
| * |
| * @return |
| */ |
| private TreeIterator stopFCNotify() { |
| TreeIterator iterator = facesConfig.eAllContents(); |
| // Stop the listener |
| while (iterator.hasNext()) { |
| EObject object = (EObject) iterator.next(); |
| object.eSetDeliver(false); |
| } |
| facesConfig.eSetDeliver(false); |
| return iterator; |
| } |
| |
| /** |
| * For performance issue, we are going to update DOM only after the EMF |
| * modifications are done. |
| */ |
| boolean isNeedBatchOperations() { |
| return needBatchOperations; |
| } |
| |
| /** |
| * @param enable |
| */ |
| public void setNeedBatchOperations(boolean enable) { |
| this.needBatchOperations = enable; |
| if (!enable) { |
| isInEvent = true; |
| postEMFChanged(); |
| isInEvent = false; |
| } else { |
| stopFCNotify(); |
| } |
| } |
| |
| private void updateFacesRule(NavigationRuleType navigationRule, |
| PageflowPage pageSource) { |
| FacesConfigFactory factory = FacesConfigFactory.eINSTANCE; |
| if (pageSource.getComment() != null) { |
| DescriptionType description = factory.createDescriptionType(); |
| description.setTextContent(pageSource.getComment()); |
| navigationRule.getDescription().clear(); |
| navigationRule.getDescription().add(description); |
| } |
| // set the navigation rule's icon |
| if (pageSource.getLargeicon() != null |
| || pageSource.getSmallicon() != null) { |
| IconType icon = factory.createIconType(); |
| if (pageSource.getLargeicon() != null) { |
| LargeIconType largeicon = factory.createLargeIconType(); |
| largeicon.setTextContent(pageSource.getLargeicon()); |
| icon.setLargeIcon(largeicon); |
| } |
| |
| if (pageSource.getSmallicon() != null) { |
| SmallIconType smallicon = factory.createSmallIconType(); |
| smallicon.setTextContent(pageSource.getSmallicon()); |
| icon.setSmallIcon(smallicon); |
| } |
| navigationRule.getIcon().clear(); |
| navigationRule.getIcon().add(icon); |
| } |
| if (pageSource.getName() != null) { |
| DisplayNameType displayName = factory.createDisplayNameType(); |
| displayName.setTextContent(pageSource.getName()); |
| navigationRule.getDisplayName().clear(); |
| navigationRule.getDisplayName().add(displayName); |
| } |
| } |
| |
| /** |
| * TODO: If we cache the case's properties in a link, then we can restore |
| * them. |
| * |
| * @param navigationCase |
| * @param link |
| */ |
| // TODO: not used, dead? |
| // private void updateFacesCase(NavigationCaseType navigationCase, |
| // PageflowLink link) { |
| // FacesConfigFactory factory = FacesConfigFactory.eINSTANCE; |
| // if (link.getComment() != null) { |
| // DescriptionType description = factory.createDescriptionType(); |
| // description.setTextContent(link.getComment()); |
| // navigationCase.getDescription().clear(); |
| // navigationCase.getDescription().add(description); |
| // } |
| // // set the navigation rule's icon |
| // if (link.getLargeicon() != null || link.getSmallicon() != null) { |
| // IconType icon = factory.createIconType(); |
| // if (link.getLargeicon() != null) { |
| // LargeIconType largeicon = factory.createLargeIconType(); |
| // largeicon.setTextContent(link.getLargeicon()); |
| // icon.setLargeIcon(largeicon); |
| // } |
| // |
| // if (link.getSmallicon() != null) { |
| // SmallIconType smallicon = factory.createSmallIconType(); |
| // smallicon.setTextContent(link.getSmallicon()); |
| // icon.setSmallIcon(smallicon); |
| // } |
| // navigationCase.getIcon().clear(); |
| // navigationCase.getIcon().add(icon); |
| // } |
| // if (link.getFromaction() != null) { |
| // FromActionType fromAction = factory.createFromActionType(); |
| // fromAction.setTextContent(link.getFromaction()); |
| // navigationCase.setFromAction(fromAction); |
| // } |
| // if (link.getOutcome() != null) { |
| // FromOutcomeType fromOutcome = factory.createFromOutcomeType(); |
| // fromOutcome.setTextContent(link.getOutcome()); |
| // navigationCase.setFromOutcome(fromOutcome); |
| // } |
| // } |
| |
| private void createFacesCase(PageflowLink link, PageflowPage source, |
| PageflowPage target_) { |
| NavigationRuleType rule = FacesConfigFactory.eINSTANCE |
| .createNavigationRuleType(); |
| FromViewIdType from = FacesConfigFactory.eINSTANCE |
| .createFromViewIdType(); |
| from.setTextContent((source).getPath()); |
| rule.setFromViewId(from); |
| NavigationCaseType navCase = FacesConfigFactory.eINSTANCE |
| .createNavigationCaseType(); |
| ToViewIdType toView = FacesConfigFactory.eINSTANCE.createToViewIdType(); |
| toView.setTextContent((target_).getPath()); |
| navCase.setToViewId(toView); |
| rule.getNavigationCase().add(navCase); |
| facesConfig.getNavigationRule().add(rule); |
| updateFacesRule(rule, source); |
| source.getFCElements().add(from); |
| target_.getFCElements().add(toView); |
| link.getFCElements().add(navCase); |
| mapCases2Links.put(navCase, link); |
| } |
| |
| private void removePageflowPage(PageflowPage source) { |
| Assert.isTrue(source.getOutlinks().size() == 0 |
| && source.getInlinks().size() == 0); |
| pageflow.getNodes().remove(source); |
| } |
| |
| void removeCase(NavigationCaseType navCase) { |
| NavigationRuleType rule = (NavigationRuleType) navCase.eContainer(); |
| (rule).getNavigationCase().remove(navCase); |
| if (rule.getNavigationCase().size() == 0) { |
| facesConfig.getNavigationRule().remove(rule); |
| } |
| } |
| |
| /** |
| * Remove a link in pageflow model. |
| * |
| * @param pLink |
| */ |
| private void removeLink(PageflowLink pLink) { |
| // Link |
| PageflowPage source = (PageflowPage) pLink.getSource(); |
| PageflowPage target_ = (PageflowPage) pLink.getTarget(); |
| pLink.getPageflow().getLinks().remove(pLink); |
| source.getOutlinks().remove(pLink); |
| target_.getInlinks().remove(pLink); |
| // Navigation case |
| pLink.getFCElements().clear(); |
| cleanPage(source); |
| cleanPage(target_); |
| } |
| |
| /** |
| * Remove a link in pageflow model. |
| * |
| * @param pLink |
| */ |
| void changePFLinkStart(PageflowLink pLink, String newValue) { |
| PageflowPage newPage = null; |
| if ((newPage = getValidPFPageInCache(newValue)) != null) { |
| if (newValue.equals(((PageflowPage) pLink.getSource()).getPath())) { |
| return; |
| } |
| } else if ((newPage = TransformUtil.findPage(newValue, pageflow)) == null) { |
| return; |
| } |
| |
| // remove old case |
| NavigationCaseType caseType = (NavigationCaseType) pLink |
| .getFCElements().getData().get(0); |
| //NavigationRuleType rule = (NavigationRuleType) caseType.eContainer(); |
| removeCase(caseType); |
| |
| // create new rule / case |
| NavigationCaseType newCase = FacesConfigFactory.eINSTANCE |
| .createNavigationCaseType(); |
| ToViewIdType toView = FacesConfigFactory.eINSTANCE.createToViewIdType(); |
| toView.setTextContent(caseType.getToViewId().getTextContent()); |
| newCase.setToViewId(toView); |
| |
| NavigationRuleType newRule = FacesConfigFactory.eINSTANCE |
| .createNavigationRuleType(); |
| FromViewIdType fromView = FacesConfigFactory.eINSTANCE |
| .createFromViewIdType(); |
| fromView.setTextContent(newValue); |
| newRule.setFromViewId(fromView); |
| newRule.getNavigationCase().add(newCase); |
| facesConfig.getNavigationRule().add(newRule); |
| |
| // update |
| // updateNode(rule, newRule); |
| updateNode(caseType, newCase); |
| |
| pLink.getFCElements().clear(); |
| pLink.getFCElements().add(newCase); |
| pLink.setSource(newPage); |
| |
| updatePageflowElements(pageflow, newCase); |
| } |
| |
| private void updateNode(EObject old, EObject newOne) { |
| if (old instanceof NavigationRuleType) { |
| ((NavigationRuleType) newOne).getDescription().clear(); |
| ((NavigationRuleType) newOne).getDescription().addAll( |
| ((NavigationRuleType) old).getDescription()); |
| ((NavigationRuleType) newOne).getDisplayName().clear(); |
| ((NavigationRuleType) newOne).getDisplayName().addAll( |
| ((NavigationRuleType) old).getDisplayName()); |
| ((NavigationRuleType) newOne).getDescription().clear(); |
| ((NavigationRuleType) newOne).getIcon().clear(); |
| ((NavigationRuleType) newOne).getIcon().addAll( |
| ((NavigationRuleType) old).getIcon()); |
| } else if (old instanceof NavigationCaseType) { |
| ((NavigationCaseType) newOne).getDescription().clear(); |
| ((NavigationCaseType) newOne).getDescription().addAll( |
| ((NavigationCaseType) old).getDescription()); |
| ((NavigationCaseType) newOne).getDisplayName().clear(); |
| ((NavigationCaseType) newOne).getDisplayName().addAll( |
| ((NavigationCaseType) old).getDisplayName()); |
| ((NavigationCaseType) newOne).getDescription().clear(); |
| ((NavigationCaseType) newOne).getIcon().clear(); |
| ((NavigationCaseType) newOne).getIcon().addAll( |
| ((NavigationCaseType) old).getIcon()); |
| ((NavigationCaseType) newOne) |
| .setFromAction(((NavigationCaseType) old).getFromAction()); |
| ((NavigationCaseType) newOne) |
| .setFromOutcome(((NavigationCaseType) old).getFromOutcome()); |
| } |
| } |
| |
| void changePFLinkEnd(PageflowLink pLink, String newValue) { |
| PageflowPage newPage = null; |
| if ((newPage = getValidPFPageInCache(newValue)) != null) { |
| if (newValue.equals(((PageflowPage) pLink.getSource()).getPath())) { |
| return; |
| } |
| } else if ((newPage = TransformUtil.findPage(newValue, pageflow)) == null) { |
| return; |
| } |
| |
| // remove old case |
| NavigationCaseType caseType = (NavigationCaseType) pLink |
| .getFCElements().getData().get(0); |
| ToViewIdType toView = caseType.getToViewId(); // FacesConfigFactory.eINSTANCE.createToViewIdType(); |
| if (toView == null) { |
| toView = FacesConfigFactory.eINSTANCE.createToViewIdType(); |
| } |
| toView.setTextContent(newValue); |
| caseType.setToViewId(toView); |
| |
| pLink.setTarget(newPage); |
| |
| updatePageflowElements(pageflow, caseType); |
| } |
| |
| void removeLink(NavigationCaseType caseType) { |
| PageflowLink link = (PageflowLink) mapCases2Links.get(caseType); |
| if (link != null) { |
| removeLink(link); |
| } |
| } |
| |
| void addLink(PageflowPage source, PageflowPage target_, PageflowLink value) { |
| if (source != null && target_ != null && value != null) { |
| createFacesCase(value, source, target_); |
| } |
| } |
| |
| private void cleanPage(PageflowPage source) { |
| if (source.getInlinks().size() == 0 && source.getOutlinks().size() == 0) { |
| removePageflowPage(source); |
| } |
| source.update(); |
| } |
| |
| void refreshPFAdapter(EObject object) { |
| TreeIterator content = object.eAllContents(); |
| while (content.hasNext()) { |
| Object next = content.next(); |
| adapt((EObject) next); |
| } |
| adapt(object); |
| } |
| |
| void refreshFCAdapter(EObject object) { |
| List rules = facesConfig.getNavigationRule(); |
| if (rules != null) { |
| for (int i = 0; i < rules.size(); i++) { |
| NavigationRuleType rule = (NavigationRuleType) rules.get(i); |
| adapt(rule); |
| TreeIterator children = rule.eAllContents(); |
| while (children.hasNext()) { |
| adapt((EObject) children.next()); |
| } |
| } |
| } |
| adapt(facesConfig); |
| } |
| |
| /** |
| * @param facesConfig |
| */ |
| public void setFacesConfig(FacesConfigType facesConfig) { |
| this.facesConfig = facesConfig; |
| refreshFCAdapter(facesConfig); |
| } |
| |
| /** |
| * @param pageflow |
| */ |
| public void setPageflow(Pageflow pageflow) { |
| this.pageflow = pageflow; |
| pageflow.eAdapters().add(this); |
| refreshPFAdapter(pageflow); |
| } |
| |
| /** |
| * Install compatible synchronization adapter for particular object. |
| * |
| * @param object |
| */ |
| public void adapt(EObject object) { |
| if (object != null && !isAdapted(object)) { |
| if (object instanceof PageflowElement) { |
| object.eAdapters().add(new PF2FCSynchronizer(this)); |
| } else { |
| object.eAdapters().add(new FC2PFSynchronizer(this)); |
| } |
| } |
| } |
| |
| /** |
| * Remove the synchronization adapter. |
| * |
| * @param object |
| */ |
| public void unAdapt(EObject object) { |
| Iterator adapters = object.eAdapters().iterator(); |
| while (adapters.hasNext()) { |
| Object adapter = adapters.next(); |
| if (adapter instanceof FC2PFSynchronizer |
| || adapter instanceof PF2FCSynchronizer) { |
| adapters.remove(); |
| } |
| } |
| } |
| |
| /** |
| * @param object |
| * @return true if this transformer adapts object |
| */ |
| public boolean isAdapted(EObject object) { |
| if (object != null) { |
| Iterator adapters = object.eAdapters().iterator(); |
| while (adapters.hasNext()) { |
| Object adapter = adapters.next(); |
| if (adapter instanceof FC2PFSynchronizer |
| || adapter instanceof PF2FCSynchronizer) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * clear the internal maps |
| */ |
| public void clearCaches() { |
| mapPaths2PF.clear(); |
| mapCases2Links.clear(); |
| } |
| |
| /** |
| * dispose of this object. |
| */ |
| public void dispose() { |
| clearCaches(); |
| Pageflow pageFlow = getPageflow(); |
| |
| if (pageFlow != null) |
| { |
| pageFlow.dispose(); |
| } |
| } |
| |
| public Notifier getTarget() { |
| return null; |
| } |
| |
| public boolean isAdapterForType(Object type) { |
| return false; |
| } |
| |
| public void setTarget(Notifier newTarget) { |
| // do nothing |
| } |
| |
| /** |
| * @param caseType |
| * @return the from view id in caseType |
| */ |
| public static FromViewIdType getSource(NavigationCaseType caseType) { |
| if (caseType.eContainer() instanceof NavigationRuleType) { |
| NavigationRuleType rule = (NavigationRuleType) caseType |
| .eContainer(); |
| return rule.getFromViewId(); |
| } |
| return null; |
| } |
| |
| private PageflowPage getOrCreateStartPage(NavigationCaseType navCase) {// FromViewIdType |
| PageflowPage startPageflowNode = null; |
| String path = "*"; //$NON-NLS-1$ |
| NavigationRuleType rule = (NavigationRuleType) navCase.eContainer(); |
| FromViewIdType source = getSource(navCase); |
| if (source != null) { |
| path = source.getTextContent(); |
| } |
| if (getValidPFPageInCache(path) == null) { |
| startPageflowNode = TransformUtil.findPage(path, pageflow); |
| |
| if (startPageflowNode == null) { |
| // not exist or is "*" |
| if (DEBUG) |
| System.out.println("Create new start page"); //$NON-NLS-1$ |
| startPageflowNode = createPFPage(path); |
| pageflowChanged = true; |
| } |
| mapPaths2PF.put(path, startPageflowNode); |
| PageflowTransform.getInstance().updatePageflowSourcePage( |
| startPageflowNode, rule); |
| } else { |
| startPageflowNode = (PageflowPage) mapPaths2PF.get(path); |
| } |
| if (source != null) { |
| ReferenceElement element = new PageReferenceElement( |
| startPageflowNode); |
| element.add(source); |
| startPageflowNode |
| .setReferenceLink(element.resolveReferenceString()); |
| startPageflowNode.getFCElements().add(source); |
| } |
| return startPageflowNode; |
| } |
| |
| /** |
| * Search for an existing pageflow page matching to navigation case's |
| * target, if there is no such page existing, create one. |
| * |
| * @param navCase |
| * @return |
| */ |
| private PageflowPage getOrCreateEndPage(NavigationCaseType navCase) { |
| PageflowPage endPageflowNode = null; |
| ToViewIdType target_ = navCase.getToViewId(); |
| if (target_ != null) { |
| String path = target_.getTextContent(); |
| if (getValidPFPageInCache(path) == null) { |
| endPageflowNode = TransformUtil.findPage(path, pageflow); |
| if (endPageflowNode == null) { |
| endPageflowNode = createPFPage(path); |
| if (DEBUG) |
| System.out.println("Create new end page"); //$NON-NLS-1$ |
| pageflowChanged = true; |
| } |
| mapPaths2PF.put(path, endPageflowNode); |
| PageflowTransform.getInstance().updatePageflowTargetPage( |
| endPageflowNode, navCase); |
| } else { |
| endPageflowNode = (PageflowPage) mapPaths2PF.get(path); |
| } |
| if (target_ != null) { |
| ReferenceElement element = new PageReferenceElement( |
| endPageflowNode); |
| element.add(target_); |
| endPageflowNode.setReferenceLink(element |
| .resolveReferenceString()); |
| endPageflowNode.getFCElements().add(target_); |
| } |
| } |
| return endPageflowNode; |
| } |
| |
| /** |
| * Return a valid cached pageflow node. |
| * |
| * @param key |
| * @return |
| */ |
| private PageflowPage getValidPFPageInCache(Object key) { |
| EObject element = (EObject) mapPaths2PF.get(key); |
| if (!TransformUtil.isValidPageflowElement(element) |
| || !(element instanceof PageflowPage) |
| || !((PageflowPage) element).getPath().equals(key)) { |
| mapPaths2PF.remove(key); |
| element = null; |
| } |
| return (PageflowPage) element; |
| } |
| |
| /** |
| * Return a valid cached pageflow link. |
| * |
| * @param caseType |
| * @return |
| */ |
| private PageflowLink getValidPFLinkInCache(EObject caseType) { |
| PageflowLink link = (PageflowLink) mapCases2Links.get(caseType); |
| if (!TransformUtil.isValidLink(link)) { |
| mapCases2Links.remove(caseType); |
| link = null; |
| } |
| return link; |
| |
| } |
| |
| /** |
| * Update pageflow model elements against faces-config navigation case. |
| * @param pageflow_ |
| * @param caseFC |
| * @return true if the pageflow was changed |
| */ |
| public boolean updatePageflowElements(Pageflow pageflow_, |
| NavigationCaseType caseFC) { |
| this.pageflowChanged = false; |
| this.pageflow = pageflow_; |
| ToViewIdType target_ = caseFC.getToViewId(); |
| if (target_ == null) { |
| return false; |
| } |
| |
| PageflowPage start = null, end = null; |
| // start page |
| start = getOrCreateStartPage(caseFC); |
| String action = null; |
| // action |
| if (caseFC.getFromAction() != null) { |
| action = caseFC.getFromAction().getTextContent(); |
| } |
| // from outcome |
| String fromOutCome = null; |
| if (caseFC.getFromOutcome() != null) { |
| fromOutCome = caseFC.getFromOutcome().getTextContent(); |
| } |
| // end page |
| end = getOrCreateEndPage(caseFC); |
| // link |
| // Is there a link in pageflow model? |
| PageflowLink link = null; |
| if ((link = findUnmappedLink(start, end, caseFC)) == null) { |
| if (end != null) { |
| if (DEBUG) |
| System.out.println("Create new link"); //$NON-NLS-1$ |
| link = createPFLink(start, end, action, fromOutCome); |
| pageflowChanged = true; |
| } |
| } |
| if (link != null) { |
| link.getFCElements().clear(); |
| link.getFCElements().add(caseFC); |
| mapCases2Links.put(caseFC, link); |
| } |
| adapt(start); |
| adapt(end); |
| adapt(caseFC); |
| adapt(link); |
| return pageflowChanged; |
| } |
| |
| private boolean cleanPageflowNavigationRule(Pageflow pageflow_) { |
| boolean dirty = false; |
| List links = pageflow_.getLinks(); |
| Iterator linksIterator = links.iterator(); |
| while (linksIterator.hasNext()) { |
| PageflowLink link = (PageflowLink) linksIterator.next(); |
| if (link.getFCElements().isEmpty()) { |
| linksIterator.remove(); |
| if (link.getSource() != null) { |
| link.getSource().getOutlinks().remove(link); |
| } |
| if (link.getTarget() != null) { |
| link.getTarget().getInlinks().remove(link); |
| } |
| dirty = true; |
| } |
| } |
| return dirty; |
| } |
| |
| /** |
| * merge the two navigation rules list between pageflow and face-config |
| * file. merge rule: 1. if the from-view-id, from-action, and from-outcome |
| * are same, they are the same navigation case, then the navigation case in |
| * face-config file should be updated by one in the pageflow. 2. otherwise |
| * the new navigation case should be created. |
| * |
| * FIXME: Not merge, only update page flow from faces-config. |
| * |
| * @param rulesFC - |
| * navigation rules in faces-config. |
| * @param navigationRulesInPageflow - |
| * navigation rules in pageflow model. |
| * |
| * @return boolean - whether add a new rule or not. |
| */ |
| private boolean updateNavigationRulesInPageflowFromFacesConfig(List rulesFC) { |
| boolean isNew = false; |
| // if the faces-config file is empty, the links should be removed. |
| if (rulesFC == null || rulesFC.isEmpty()) { |
| for (Iterator iterLink = pageflow.getLinks().iterator(); iterLink |
| .hasNext();) { |
| PageflowLink link = (PageflowLink) iterLink.next(); |
| link.getSource().getOutlinks().remove(link); |
| link.getTarget().getInlinks().remove(link); |
| } |
| pageflow.getLinks().clear(); |
| } else { |
| // Rule - Cases |
| for (Iterator iterRulesFC = rulesFC.iterator(); iterRulesFC |
| .hasNext();) { |
| NavigationRuleType ruleFC = (NavigationRuleType) iterRulesFC |
| .next(); |
| |
| List casesFC = ruleFC.getNavigationCase(); |
| for (Iterator iterCasesFC = casesFC.iterator(); iterCasesFC |
| .hasNext();) { |
| NavigationCaseType navigationCaseFC = (NavigationCaseType) iterCasesFC |
| .next(); |
| isNew |= updatePageflowElements(pageflow, navigationCaseFC); |
| } |
| } |
| } |
| isNew |= cleanPageflowNavigationRule(pageflow); |
| return isNew; |
| } |
| |
| /** |
| * Find a pageflow link that is not linked to a faces-config element. Since |
| * user might edit faces-config file with other editor, so the path is not |
| * always valid, here we still try to match link and navigation case. TODO: |
| * should we always resolve mapping from referenceLink on PageflowElement? |
| */ |
| private PageflowLink findUnmappedLink(PageflowPage start, PageflowPage end, |
| NavigationCaseType caseFC) { |
| List links = start.getOutlinks(); |
| for (int i = 0, n = links.size(); i < n; i++) { |
| PageflowLink link = (PageflowLink) links.get(i); |
| if (link.getSource() == start && link.getTarget() == end) { |
| link.update(); |
| if (link.getFCElements().isEmpty() |
| || link.getFCElements().getData().get(0) == caseFC) { |
| return link; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * create a new PFLink object according to fromOutcome attribute |
| * |
| * @param fromOutcome - |
| * PFLink's fromOutcome attribute |
| * @return - new PFLink object |
| */ |
| public PageflowLink createPFLink(String fromOutcome) { |
| PageflowLink link = null; |
| link = PageflowModelManager.getFactory().createPFLink(); |
| if (fromOutcome != null && fromOutcome.length() > 0) { |
| link.setOutcome(fromOutcome.trim()); |
| } |
| pageflow.getLinks().add(link); |
| return link; |
| } |
| |
| /** |
| * create a new PFLink object according to fromOutcome attribute |
| * @param start |
| * @param target_ |
| * @param action |
| * |
| * @param fromOutcome - |
| * PFLink's fromOutcome attribute |
| * @return - new PFLink object |
| */ |
| public PageflowLink createPFLink(PageflowNode start, PageflowNode target_, |
| String action, String fromOutcome) { |
| Assert.isTrue(start != null && target_ != null); |
| PageflowLink link = null; |
| link = createPFLink(fromOutcome); |
| link.setFromaction(action); |
| link.setSource(start); |
| link.setTarget(target_); |
| start.getOutlinks().add(link); |
| target_.getInlinks().add(link); |
| return link; |
| } |
| |
| /** |
| * Create a new PFPage according to from-view-id |
| * |
| * @param fromViewID - |
| * page's from-view-id |
| * @return the page flow page |
| */ |
| public PageflowPage createPFPage(String fromViewID) { |
| PageflowPage page = PageflowFactory.eINSTANCE.createPFPage(); |
| if (fromViewID != null && fromViewID.length() > 0) { |
| page.setPath(fromViewID.trim()); |
| page.setName(WebrootUtil.getPageNameFromWebPath(fromViewID.trim())); |
| } |
| this.pageflow.getNodes().add(page); |
| return page; |
| } |
| |
| /** |
| * update pageflow model according to the face-config model |
| * |
| * @author sfshi |
| * @return true if new rules were added |
| */ |
| public boolean updatePageflowModelFromEMF() { |
| if (pageflow != null && facesConfig != null) { |
| List navigationRulesInFacesconfig = facesConfig.getNavigationRule(); |
| clearCaches(); |
| // if add new one, we can relayout the current pageflow. |
| return updateNavigationRulesInPageflowFromFacesConfig(navigationRulesInFacesconfig); |
| } |
| return false; |
| } |
| |
| void refreshLink(NavigationCaseType caseType) { |
| PageflowLink link = getValidPFLinkInCache(caseType); |
| if (link != null) { |
| removeLink(link); |
| } |
| // update pageflow |
| if (TransformUtil.isValidFacesConfigElement(caseType)) { |
| updatePageflowElements(pageflow, caseType); |
| } |
| } |
| |
| public void notifyChanged(Notification msg) { |
| int type = msg.getEventType(); |
| switch (type) { |
| case MY_NOTIFICATION_TYPE: |
| setNeedBatchOperations(true); |
| break; |
| case MY_NOTIFICATION_TYPE1: |
| setNeedBatchOperations(false); |
| } |
| } |
| |
| /** |
| * @return true if is listening to notifications and not |
| * currently in an event |
| */ |
| public boolean isListenToNotify() { |
| return listenToNotify && !isInEvent; |
| } |
| |
| /** |
| * @return true if in event |
| */ |
| // public boolean isInEvent() { |
| // return isInEvent; |
| // } |
| |
| /** |
| * @param isInEvent |
| */ |
| public void setInEvent(boolean isInEvent) { |
| this.isInEvent = isInEvent; |
| } |
| |
| /** |
| * @return the faces config model |
| */ |
| public FacesConfigType getFacesConfig() { |
| return facesConfig; |
| } |
| |
| /** |
| * @return the root page flow |
| */ |
| public Pageflow getPageflow() { |
| return pageflow; |
| } |
| |
| /** |
| * @param value |
| * @return a new fromViewId with the text content set to value |
| */ |
| public static FromViewIdType createRLFromViewID(String value) { |
| FromViewIdType fromView = FacesConfigFactory.eINSTANCE |
| .createFromViewIdType(); |
| fromView.setTextContent(value); |
| return fromView; |
| } |
| |
| /** |
| * @param value |
| * @return a new to view with the text content set to value |
| */ |
| public static ToViewIdType createFCToViewID(String value) { |
| ToViewIdType toView = FacesConfigFactory.eINSTANCE.createToViewIdType(); |
| toView.setTextContent(value); |
| return toView; |
| } |
| } |