001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: /*
042: * VWPContentModel.java
043: *
044: * Created on April 12, 2007, 9:26 AM
045: *
046: * To change this template, choose Tools | Template Manager
047: * and open the template in the editor.
048: */
049:
050: package org.netbeans.modules.visualweb.navigation;
051:
052: import com.sun.rave.designtime.DesignBean;
053: import com.sun.rave.designtime.DesignBean;
054: import com.sun.rave.designtime.DesignContext;
055: import com.sun.rave.designtime.DesignEvent;
056: import com.sun.rave.designtime.DesignProperty;
057: import com.sun.rave.designtime.event.DesignContextListener;
058: import com.sun.rave.designtime.markup.MarkupDesignBean;
059: import java.awt.EventQueue;
060: import java.awt.Image;
061: import java.beans.BeanInfo;
062: import java.io.IOException;
063: import java.net.MalformedURLException;
064: import java.net.URL;
065: import java.util.ArrayList;
066: import java.util.Collection;
067: import java.util.List;
068: import java.util.logging.Level;
069: import java.util.logging.LogRecord;
070: import java.util.logging.Logger;
071: import javax.faces.component.ActionSource;
072: import javax.faces.component.ActionSource2;
073: import javax.swing.Action;
074: import org.netbeans.api.project.FileOwnerQuery;
075: import org.netbeans.api.project.Project;
076: import org.netbeans.modules.visualweb.api.designer.cssengine.CssProvider;
077: import org.netbeans.modules.visualweb.api.designer.cssengine.StyleData;
078: import org.netbeans.modules.visualweb.api.designer.cssengine.XhtmlCss;
079: import org.netbeans.modules.visualweb.insync.Model;
080: import org.netbeans.modules.visualweb.insync.ModelSet;
081: import org.netbeans.modules.visualweb.insync.ModelSetListener;
082: import org.netbeans.modules.visualweb.insync.UndoEvent;
083: import org.netbeans.modules.visualweb.insync.Util;
084: import org.netbeans.modules.visualweb.insync.faces.HtmlBean;
085: import org.netbeans.modules.visualweb.insync.live.LiveUnit;
086: import org.netbeans.modules.visualweb.insync.live.MethodBindDesignEvent;
087: import org.netbeans.modules.visualweb.insync.live.MethodBindDesignProperty;
088: import org.netbeans.modules.visualweb.insync.models.FacesModel;
089: import org.netbeans.modules.visualweb.insync.models.FacesModelSet;
090: import org.netbeans.modules.visualweb.project.jsf.api.JsfProjectUtils;
091: import org.netbeans.modules.web.jsf.navigation.pagecontentmodel.PageContentItem;
092: import org.netbeans.modules.web.jsf.navigation.pagecontentmodel.PageContentModel;
093: import org.openide.ErrorManager;
094: import org.openide.filesystems.FileObject;
095: import org.openide.filesystems.URLMapper;
096: import org.w3c.dom.Element;
097:
098: /**
099: *
100: * @author joelle
101: */
102: public class VWPContentModel extends PageContentModel {
103:
104: private FacesModel facesModel;
105: private Collection<PageContentItem> pageContentItems = new ArrayList<PageContentItem>();
106: private VWPContentModelProvider provider;
107: private static final Logger LOGGER = Logger
108: .getLogger(VWPContentModel.class.getName());
109: static {
110: LOGGER.setLevel(Level.FINEST);
111: }
112:
113: /** Creates a new instance of VWPContentModel
114: * @param facesModel can not be null
115: * @param pageName can not be null
116: */
117: public VWPContentModel(VWPContentModelProvider provider,
118: FacesModel facesModel) {
119: this .facesModel = facesModel;
120: this .provider = provider;
121: updatePageContentItems();
122: initListeners();
123: }
124:
125: @Override
126: protected void finalize() throws Throwable {
127: destroy();
128: super .finalize();
129: }
130:
131: public void destroy() throws IOException {
132: destroyListeners();
133: provider.removeModel(this );
134: pageContentItems.clear();
135:
136: }
137:
138: public VWPContentModel() {
139: }
140:
141: public Collection<PageContentItem> getPageContentItems() {
142: return pageContentItems;
143: }
144:
145: public void addPageContentItem(PageContentItem pageContentItem) {
146: throw new UnsupportedOperationException("Not supported yet.");
147: }
148:
149: public void removePageContentItem(PageContentItem pageContentItem) {
150: pageContentItems.remove(pageContentItem);
151: }
152:
153: public String getPageName() {
154: return facesModel.getBeanName();
155: }
156:
157: protected final FacesModel getFacesModel() {
158: return facesModel;
159: }
160:
161: private FacesModelSetListener msl;
162: private DesignContextListener dcl;
163:
164: public void initListeners() {
165: assert facesModel != null;
166:
167: LOGGER.entering("VWPContentModel", "initListeners()");
168: if (msl == null) {
169: LOGGER.finest("Adding model listener for Page: "
170: + getPageName());
171: msl = new FacesModelSetListener(this );
172: facesModel.getOwner().addModelSetListener(msl);
173: }
174: if (dcl == null) {
175: /* So you can see changes on the individual design contexts */
176: dcl = new VWPDesignContextListener(this );
177: LiveUnit liveUnit = facesModel.getLiveUnit();
178: if (liveUnit == null) {
179: facesModel.sync();
180: liveUnit = facesModel.getLiveUnit();
181: }
182: if (liveUnit != null) {
183: liveUnit.addDesignContextListener(dcl);
184: }
185: }
186: LOGGER.exiting("VWPContentModel", "initListeners()");
187: }
188:
189: public void destroyListeners() {
190:
191: LOGGER.entering("VWPContentModel", "destroyListeners()");
192: if (facesModel != null) {
193: LOGGER.finest("Removing model listener for Page: "
194: + getPageName());
195: ModelSet set = facesModel.getOwner();
196: if (set != null && msl != null) {
197: set.removeModelSetListener(msl);
198: msl = null;
199: }
200: if (dcl != null && facesModel != null) {
201: LiveUnit liveUnit = facesModel.getLiveUnit();
202: if (liveUnit != null) {
203: liveUnit.removeDesignContextListener(dcl);
204: }
205: dcl = null;
206: }
207: }
208:
209: LOGGER.exiting("VWPContentModel", "destroyListeners()");
210: }
211:
212: protected final void updateModel() {
213: updatePageContentItems();
214: handleModelChangeEvent();
215: }
216:
217: /**
218: * Class which listens to DOM and project events
219: */
220: /*
221: private class FacesModelSetListener implements ModelSetListener {
222: final VWPContentModel vwpContentModel;
223: public FacesModelSetListener(VWPContentModel vwpContentModel) {
224: this.vwpContentModel = vwpContentModel;
225: }
226: public void modelAdded(Model model) {
227: LOGGER.finest("Model Added()");
228: //DO NOTHING
229: }
230: public void modelChanged(Model model) {
231: LOGGER.finest("Model Changed()");
232: if ((model == facesModel) || (model.getFile().getExt().equals("jspf") && isKnownFragementModel(facesModel, facesModel.getRootBean(), model))) {
233: EventQueue.invokeLater(new Runnable() {
234: public void run() {
235: updatePageContentItems();
236: vwpContentModel.handleModelChangeEvent();
237: }
238: });
239: }
240: }
241: public void modelRemoved(Model model) {
242: LOGGER.finest("Model Removed()");
243: //DO NOTHING
244: }
245: public void modelProjectChanged() {
246: LOGGER.finest("Model Project Changed()");
247: //DO NOTHING
248: }
249: }
250: */
251: /**
252: * Recursively locate all UICommand beans and add them to the given list
253: * @ fill beans with the list of designBeans
254: */
255: private static void findCommandBeans(FacesModel model,
256: DesignBean container, List<DesignBean> beans,
257: boolean includeFragments) {
258: if (container == null) {
259: return;
260: }
261: for (DesignBean designBean : container.getChildBeans()) {
262:
263: // To be more general, check if instance of ActionSource and ActionSource2 instead of UICommand.
264: // Check if it extends actionsSource and/or is hidden. Don't add otherwise.
265: if (designBean.getInstance() instanceof ActionSource
266: || designBean.getInstance() instanceof ActionSource2) {
267: /**** HACK, HACK, HACK *****
268: * DropDown is an instance of ActionSource but does not completely define the ActionSource interface.
269: * Unfortunatley there is not enough time to redo this component, so we are having to put a hack into
270: * navigator. I hate doing this. -Joelle
271: */
272: if (designBean
273: .getInstance()
274: .getClass()
275: .getName()
276: .equals(
277: "com.sun.rave.web.ui.component.DropDown")
278: || (designBean.getInstance().getClass()
279: .getName()
280: .equals("com.sun.webui.jsf.component.DropDown"))) {
281: continue;
282: }
283: beans.add(designBean);
284: }
285: String className = designBean.getInstance() != null ? designBean
286: .getInstance().getClass().getName()
287: : "";
288: if (includeFragments
289: && className.equals(HtmlBean.PACKAGE
290: + "Jsp_Directive_Include")) {
291: // NOI18N
292: // directive include -- look for referenced beans too in the fragment
293: FacesModel fragmentModel = getFragmentModel(model,
294: designBean);
295: if (fragmentModel != null) {
296: findCommandBeans(fragmentModel, fragmentModel
297: .getRootBean(), beans, true);
298: }
299: } else if (designBean.isContainer()) {
300: /* every tag set is like a container.. Page.. html...
301: * you really have to drill down (in this case recursively)
302: * to find the components.
303: */
304: findCommandBeans(model, designBean, beans,
305: includeFragments);
306: }
307: }
308: }
309:
310: /* Check if a fragment model exists in this faces model */
311: protected boolean isKnownFragementModel(FacesModel theModel,
312: DesignBean container, Model possibleFragmentModel) {
313: //DesignBean container = facesModel.getRootBean();
314: if (container == null) {
315: return false;
316: }
317: boolean found = false;
318: for (DesignBean designBean : container.getChildBeans()) {
319: String className = designBean.getInstance() != null ? designBean
320: .getInstance().getClass().getName()
321: : "";
322: if (className.equals(HtmlBean.PACKAGE
323: + "Jsp_Directive_Include")) {
324: // NOI18N
325: //if ( designBean.isContainer() ) {
326: FacesModel fragmentModel = getFragmentModel(theModel,
327: designBean);
328: if (fragmentModel != null
329: && fragmentModel.equals(possibleFragmentModel)) {
330: return true;
331: }
332: } else if (designBean.isContainer()) {
333: found = isKnownFragementModel(theModel, designBean,
334: possibleFragmentModel);
335: if (found) {
336: return true;
337: }
338: }
339: }
340: return false;
341: }
342:
343: private static final Logger LOG = Logger
344: .getLogger("org.netbeans.modules.visualweb.navigation");
345: private static final Image commandIcon = org.openide.util.Utilities
346: .loadImage("com/sun/rave/navigation/command.gif"); // NOI18N
347:
348: // private boolean updateBeans() {
349: private boolean updatePageContentItems() {
350: if (facesModel != null && !facesModel.isBusted()) {
351: DesignBean container = facesModel.getRootBean();
352: List<DesignBean> zoomedBeans = new ArrayList<DesignBean>();
353: if (container != null) {
354: findCommandBeans(facesModel, container, zoomedBeans,
355: true);
356: LOG.fine("Container or RootBean found for page: "
357: + getPageName());
358: } else {
359: LOG
360: .fine("Container or RootBean is null for the facesModel of page: "
361: + getPageName());
362: return false;
363: }
364:
365: pageContentItems.clear();
366: // p.setBeans(new ArrayList());
367: // Create page beans structure
368: for (DesignBean bean : zoomedBeans) {
369: String name = bean.getInstanceName();
370:
371: /* designContextName may reveal a sub-page or fragement*/
372: String designContextName = bean.getDesignContext()
373: .getDisplayName();
374:
375: /* If the page name does not match the designContext page name, then prepend it to the NavigableComponent name. */
376: // int lastIndex = pageName.lastIndexOf('.');
377: // if( !pageName.substring(0,lastIndex).equals(designContextName)) {
378: if (!getPageName().equals(designContextName)) {
379: name = designContextName + ":" + name;
380: }
381:
382: BeanInfo bi = bean.getBeanInfo();
383: // XXX Find a way to cache the image icon (repaint of icon slow)
384: Image icon = bi != null ? bi
385: .getIcon(BeanInfo.ICON_COLOR_16x16) : null;
386: if (icon == null) {
387: // use backup image
388: icon = commandIcon;
389: }
390: String javaeePlatform = JsfProjectUtils
391: .getJ2eePlatformVersion(getProject());
392: DesignProperty pr;
393: if ((javaeePlatform != null)
394: && JsfProjectUtils.JAVA_EE_5
395: .equals(javaeePlatform)) {
396: pr = bean.getProperty("actionExpression"); // NOI18N
397: } else {
398: pr = bean.getProperty("action"); // NOI18N
399: }
400:
401: String action = pr != null ? pr.getValueSource()
402: : "Unknown"; // NOI18N
403: Object actionO = pr != null ? pr.getValue() : null;
404:
405: /* TODO: support actionRefs !CQ MethodBinding
406: if (action == null || action.length() == 0) {
407: // See if we have an action ref, and if so visually
408: // indicate that this component binds to a page
409: // that is decided on the fly / dynamically
410: //!CQ this will need to be integrated with the above since all actions are now refs
411: }
412: */
413:
414: String outcome = action;
415: // NavigableComponent b = new NavigableComponent(bean, action, p, name, icon);
416: if (action != null && action.startsWith("#{")) {
417: // Looks like value binding: dynamic navigation.
418: //COMEBACKTO - b.dynamic = true;
419: if (pr instanceof MethodBindDesignProperty) {
420: MethodBindDesignProperty mpr = (MethodBindDesignProperty) pr;
421: MethodBindDesignEvent mev = mpr
422: .getEventReference();
423: if (mev != null) {
424: outcome = mev.getHandlerMethodReturn();
425: }
426: }
427: }
428: PageContentItem pageContentItem = new VWPContentItem(
429: this , bean, name, outcome, icon);
430: pageContentItems.add(pageContentItem);
431: // p.getBeans().add(b);T
432: }
433: return true;
434: } else {
435: return false;
436: // TODO: add some kind of error badge to the GUI
437: }
438: }
439:
440: private static FacesModel getFragmentModel(FacesModel model,
441: DesignBean fragment) {
442:
443: DesignProperty prop = fragment.getProperty("file"); // NOI18N
444: if (prop == null) {
445: return null;
446: }
447: Object fileO = prop.getValue();
448: if (!(fileO instanceof String)) {
449: return null;
450: }
451: String file = (String) fileO;
452: if ((file == null) || (file.length() == 0)) {
453: return null;
454: }
455: URL reference = model.getMarkupUnit().getBase();
456: URL url = null;
457: try {
458: url = new URL(reference, file); // XXX what if it's absolute?
459: if (url == null) {
460: return null;
461: }
462: } catch (MalformedURLException e) {
463: ErrorManager.getDefault().notify(e);
464: return null;
465: }
466:
467: Project project = model.getProject();
468: FacesModelSet models = FacesModelSet.getInstance(project);
469: if (models == null) {
470: return null;
471: }
472: FileObject fo = URLMapper.findFileObject(url);
473: if (fo != null) {
474: FacesModel fragmentModel = models.getFacesModel(fo);
475: if (fragmentModel != null) {
476: return fragmentModel;
477: }
478: }
479: return null;
480: }
481:
482: private Project project = null;
483:
484: public Project getProject() {
485: if (project == null) {
486: project = FileOwnerQuery.getOwner(facesModel.getFile());
487: }
488: return project;
489: }
490:
491: /**
492: * Add a navigation link from page "from" to page "to"
493: * this used to be setOutcome
494: * @param contentItem
495: * @param caseAction
496: * @param rename boolean
497: */
498: public void setCaseOutcome(VWPContentItem contentItem,
499: String caseOutcome, boolean rename) {
500: assert caseOutcome != null && caseOutcome.length() > 0;
501:
502: DesignProperty addLinkToDP = null;
503: DesignBean designBean = contentItem.getDesignBean();
504: if (designBean != null) {
505: FileOwnerQuery.getOwner(facesModel.getFile());
506: String javaeePlatform = JsfProjectUtils
507: .getJ2eePlatformVersion(getProject());
508: if ((javaeePlatform != null)
509: && JsfProjectUtils.JAVA_EE_5.equals(javaeePlatform)) {
510: addLinkToDP = designBean
511: .getProperty("actionExpression"); // NOI18N
512: } else {
513: addLinkToDP = designBean.getProperty("action"); // NOI18N
514: }
515: }
516: if (setCaseOutcome(contentItem, caseOutcome, addLinkToDP,
517: rename)) {
518: // updatePageContentItems();
519: }
520: }
521:
522: /**
523: * Add a navigation link from page "from" to page "to"
524: * This used to be setOutcomeNoLayout
525: */
526: private boolean setCaseOutcome(VWPContentItem contentItem,
527: String caseOutcome, DesignProperty addLinkToDP,
528: boolean rename) {
529: String oldCaseOutcome;
530: oldCaseOutcome = contentItem.getFromOutcome();
531: String javaeePlatform = null;
532:
533: Collection<PageContentItem> items = getPageContentItems();
534: if (items != null && items.size() > 0) {
535: // updatePageContentItems(); //just incase the user had made changes
536: UndoEvent undo = null;
537: try {
538: undo = facesModel.writeLock(null);
539:
540: // Are there any beans on the page referring to that
541: // action? If so, update their action handlers too!
542: for (PageContentItem pageContentItem : items) {
543: if (pageContentItem instanceof VWPContentItem) {
544: DesignBean designBean = ((VWPContentItem) pageContentItem)
545: .getDesignBean();
546: if (designBean != null) {
547: DesignProperty actionDP = getActionProperty(designBean);
548: if (actionDP != null) {
549: // dom't check equals if oldOutcome is null.
550: boolean setValueSource = oldCaseOutcome != null
551: && oldCaseOutcome
552: .equals(actionDP
553: .getValueSource()); //Causes problems when there is the same casename.
554: if (actionDP instanceof MethodBindDesignProperty) {
555: MethodBindDesignProperty mpr = (MethodBindDesignProperty) actionDP;
556: MethodBindDesignEvent mev = mpr
557: .getEventReference();
558: if (mev != null) {
559: boolean modify = false;
560: // If rename, set the value of all the beans action property to new outcome,
561: // if the action property has current value equal to outcome
562: if (rename) {
563: if ((oldCaseOutcome != null)
564: && oldCaseOutcome
565: .equals(mev
566: .getHandlerMethodReturn())) {
567: modify = true;
568: }
569: } else {
570: // Modify only the current bean
571: if (addLinkToDP == actionDP) {
572: modify = true;
573: }
574: }
575: //Does this modify the java method?
576: if (modify) {
577: if (mev.getHandlerName() == null) {
578: setValueSource = true;
579: } else {
580: //When link is created for the first time,
581: //oldOutcome and outcome are same
582: //But what if a link was never there and there is already an assigned return case
583: if (oldCaseOutcome != null
584: && oldCaseOutcome
585: .equals(caseOutcome)) {
586: if (mev
587: .getHandlerMethodReturn() != null) {
588: oldCaseOutcome = mev
589: .getHandlerMethodReturn()
590: .toString();
591: } else {
592: oldCaseOutcome = null;
593: }
594: }
595: try {
596: mev
597: .updateReturnStrings(
598: oldCaseOutcome,
599: caseOutcome);
600: } catch (NullPointerException npe) {
601: LOGGER
602: .severe("NullPointerException: Failed to update return strings\n"
603: + "Source Class: org.netbeans.modules.visualweb.navigation.VWPContentModel\n"
604: + "Method: setCaseOutcome()\n"
605: + "Call: mev.updateReturnStrings( "
606: + oldCaseOutcome
607: + ", "
608: + caseOutcome
609: + " )\n");
610: // LogRecord record = new LogRecord(Level.WARNING, "Failed to update return strings.");
611: // record.setSourceClassName("VWPContentModel");
612: // record.setSourceMethodName("setCaseOutcome(VWPContentItem contentItem, String caseOutcome, DesignProperty addLinkToDP, boolean rename)");
613: // record.setParameters(new Object[] {contentItem, caseOutcome, addLinkToDP, rename});
614: // record.setThrown(npe);
615: // LOGGER.log(record);
616: throw npe;
617: }
618:
619: setValueSource = false;
620: }
621: }
622: }
623: }
624: //Do this simply modify the jsp property?
625: if (setValueSource) {
626: actionDP
627: .setValueSource(caseOutcome);
628: }
629: }
630: }
631: }
632: }
633: } finally {
634: facesModel.writeUnlock(undo);
635: addLinkToDP = null;
636: }
637: }
638: return true;
639: }
640:
641: private DesignProperty getActionProperty(DesignBean designBean) {
642: String javaeePlatform;
643: javaeePlatform = JsfProjectUtils
644: .getJ2eePlatformVersion(getProject());
645: DesignProperty pr;
646: if ((javaeePlatform != null)
647: && JsfProjectUtils.JAVA_EE_5.equals(javaeePlatform)) {
648: pr = designBean.getProperty("actionExpression"); // NOI18N
649: if (pr != null) {
650: DesignEvent event = facesModel
651: .getDefaultEvent(designBean);
652: if (event != null) {
653: try {
654: facesModel.createEventHandler(event);
655: } catch (NullPointerException npe) {
656: npe.printStackTrace();
657: System.out.println("Event Handler Name: "
658: + event.getHandlerName());
659: System.out
660: .println("Event Handler Method Name: "
661: + event
662: .getHandlerMethodSource());
663: System.out.println("DesignBean Info: "
664: + designBean.getBeanInfo());
665: }
666: }
667: }
668: } else {
669: pr = designBean.getProperty("action"); // NOI18N
670: }
671: return pr;
672: }
673:
674: public VWPContentActions actions;
675:
676: public Action[] getActions() {
677: if (actions == null) {
678: actions = new VWPContentActions(this );
679: }
680: return (actions != null) ? actions.getVWPContentModelActions()
681: : null;
682: }
683:
684: public VWPContentActions getActionsFactory() {
685: if (actions == null) {
686: actions = new VWPContentActions(this );
687: }
688: return actions;
689: }
690:
691: public PageContentItem addPageBean(int type) {
692:
693: String javaeePlatform = JsfProjectUtils
694: .getJ2eePlatformVersion(facesModel.getProject());
695: DesignBean designBean = addComponent("createComponent",
696: VWPContentUtilities.getBeanClassName(javaeePlatform,
697: type));
698:
699: PageContentItem item = solveNavComponent(designBean);
700:
701: return item;
702: }
703:
704: private PageContentItem solveNavComponent(DesignBean designBean) {
705: if (designBean == null || getPageName() == null) {
706: return null;
707: }
708:
709: //To figure out navigable component.
710: String name = designBean.getInstanceName();
711:
712: /* designContextName may reveal a sub-page or fragement*/
713: String designContextName = designBean.getDesignContext()
714: .getDisplayName();
715:
716: /* If the page name does not match the designContext page name, then prepend it to the NavigableComponent name. */
717:
718: if (!getPageName().equals(designContextName)) {
719: name = designContextName + ":" + name;
720: }
721:
722: BeanInfo bi = designBean.getBeanInfo();
723: // XXX Find a way to cache the image icon (repaint of icon slow)
724: Image icon = bi != null ? bi.getIcon(BeanInfo.ICON_COLOR_16x16)
725: : null;
726: if (icon == null) {
727: // use backup image
728: icon = commandIcon;
729: }
730: String javaeePlatform = JsfProjectUtils
731: .getJ2eePlatformVersion(getProject());
732: DesignProperty pr;
733: if ((javaeePlatform != null)
734: && JsfProjectUtils.JAVA_EE_5.equals(javaeePlatform)) {
735: pr = designBean.getProperty("actionExpression"); // NOI18N
736: } else {
737: pr = designBean.getProperty("action"); // NOI18N
738: }
739:
740: String action = pr != null ? pr.getValueSource() : "Unknown"; // NOI18N
741: PageContentItem item = new VWPContentItem(this , designBean,
742: name, action, icon);
743: // NavigableComponent navComp = new NavigableComponent(designBean, action, page, name, icon);
744: return item;
745: }
746:
747: public void deleteCaseOutcome(VWPContentItem item) {
748: UndoEvent undo = null;
749: // DesignBean designBean = item.getDesignBean();
750: String fromOutcome = item.getFromOutcome();
751:
752: if (fromOutcome == null) {
753: LOG
754: .warning("From outcome is returning null for the given item: "
755: + item.getName());
756: return;
757: }
758:
759: DesignBean container = facesModel.getRootBean();
760: List<DesignBean> beans = new ArrayList<DesignBean>();
761: findCommandBeans(facesModel, container, beans, false);
762: try {
763: undo = facesModel.writeLock(null); //!CQ TODO: nice description
764: for (DesignBean designBean : beans) {
765: DesignProperty pr = null;
766: String javaeePlatform = JsfProjectUtils
767: .getJ2eePlatformVersion(getProject());
768: if ((javaeePlatform != null)
769: && JsfProjectUtils.JAVA_EE_5
770: .equals(javaeePlatform)) {
771: pr = designBean.getProperty("actionExpression");
772: } else {
773: pr = designBean.getProperty("action");
774: }
775: // DesignProperty pr = designBean.getProperty("action"); // NOI18N
776: if (pr != null
777: && fromOutcome.equals(pr.getValueSource())) {
778: // Yes, this action bound to this port
779: pr.unset(); // means "reset" despite the name
780: }
781: //update the java source
782: if (pr instanceof MethodBindDesignProperty) {
783: MethodBindDesignProperty mpr = (MethodBindDesignProperty) pr;
784: MethodBindDesignEvent mev = mpr.getEventReference();
785: if (mev != null && mev.getHandlerName() != null) {
786: mev.updateReturnStrings(fromOutcome, null);
787: }
788: }
789: }
790: } finally {
791: facesModel.writeUnlock(undo);
792: }
793: }
794:
795: private DesignBean addComponent(String lockDesc, String className) {
796: LOGGER
797: .entering(VWPContentModel.class.getName(),
798: "addComponent");
799: UndoEvent undo = null;
800: DesignBean bean = null;
801: try {
802: undo = facesModel.writeLock(lockDesc);
803: LiveUnit liveUnit = facesModel.getLiveUnit();
804: if (liveUnit == null) {
805: LOGGER.finest("First attempt to get LiveUnit failed.");
806: /* sync model to try to get the live unit */
807: facesModel.sync();
808: LOGGER.finest("Trying to get LiveUnit by Syncing.");
809: liveUnit = facesModel.getLiveUnit();
810: if (liveUnit == null) {
811: LOGGER.fine("LiveUnit is still null.");
812: return null;
813: }
814: }
815: bean = liveUnit.createBean(className, null, null);
816: if (bean == null) {
817: return bean;
818: }
819:
820: // XXX #106338 Hacking positioning of the bean correctly (in the grid).
821: if (bean instanceof MarkupDesignBean) {
822: initMarkupDesignBeanPosition((MarkupDesignBean) bean);
823: }
824:
825: facesModel.beanCreated(bean);
826: } catch (Exception e) {
827: ErrorManager.getDefault().notify(e);
828: } finally {
829: facesModel.writeUnlock(undo);
830: }
831: facesModel.flush();
832: LOGGER.exiting(VWPContentModel.class.getName(), "addComponent");
833: return bean;
834: }
835:
836: /**
837: * Open the source handler for the given page item. This action allows
838: * a user to jump directly to the source for the given item.
839: **/
840: public void openPageHandler(PageContentItem item) {
841: if (item instanceof VWPContentItem) {
842: VWPContentItem vwpItem = (VWPContentItem) item;
843:
844: /**
845: * At first it seems that we can just used the stored facesModel,
846: * however is some case the designBean comes from a page fragment
847: * and therefore we need to get the model in which it exists.
848: **/
849: DesignBean bean = vwpItem.getDesignBean();
850: DesignContext designContext = bean.getDesignContext();
851: if (designContext instanceof LiveUnit) {
852: ((LiveUnit) designContext).getModel()
853: .openDefaultHandler(vwpItem.getDesignBean());
854: }
855: }
856: }
857:
858: private void initMarkupDesignBeanPosition(MarkupDesignBean bean) {
859: if (Util.isGridMode(facesModel)) {
860: // XXX There should be some API in the designTime/insync?
861: Element element = bean.getElement();
862: List<StyleData> addStyle = new ArrayList<StyleData>();
863:
864: addStyle.add(new StyleData(XhtmlCss.POSITION_INDEX,
865: CssProvider.getValueService().getAbsoluteValue()));
866: addStyle.add(new StyleData(XhtmlCss.LEFT_INDEX, Integer
867: .toString(0)
868: + "px")); // NOI18N
869: addStyle.add(new StyleData(XhtmlCss.TOP_INDEX, Integer
870: .toString(0)
871: + "px")); // NOI18N
872: List<StyleData> removeStyle = new ArrayList<StyleData>();
873: removeStyle.add(new StyleData(XhtmlCss.RIGHT_INDEX));
874: removeStyle.add(new StyleData(XhtmlCss.BOTTOM_INDEX));
875:
876: Util.updateLocalStyleValuesForElement(element, addStyle
877: .toArray(new StyleData[addStyle.size()]),
878: removeStyle.toArray(new StyleData[removeStyle
879: .size()]));
880: } else {
881: // Float, no op now.
882: }
883: }
884: }
|