//------------------------------------------------------------------------------ // Copyright (c) 2005, 2007 IBM Corporation 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: // IBM Corporation - initial implementation //------------------------------------------------------------------------------ package org.eclipse.epf.publishing.services; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.emf.common.notify.AdapterFactory; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.edit.provider.ComposedAdapterFactory; import org.eclipse.emf.edit.provider.ITreeItemContentProvider; import org.eclipse.epf.common.serviceability.DebugTrace; import org.eclipse.epf.common.utils.FileUtil; import org.eclipse.epf.common.utils.StrUtil; import org.eclipse.epf.common.utils.Timer; import org.eclipse.epf.library.configuration.ConfigurationFilter; import org.eclipse.epf.library.configuration.ConfigurationHelper; import org.eclipse.epf.library.edit.IFilter; import org.eclipse.epf.library.edit.TngAdapterFactory; import org.eclipse.epf.library.edit.configuration.PracticeSubgroupItemProvider; import org.eclipse.epf.library.edit.process.IBSItemProvider; import org.eclipse.epf.library.edit.util.ProcessUtil; import org.eclipse.epf.library.edit.util.Suppression; import org.eclipse.epf.library.edit.util.TngUtil; import org.eclipse.epf.library.layout.Bookmark; import org.eclipse.epf.library.layout.IElementLayout; import org.eclipse.epf.library.layout.elements.ActivityLayout; import org.eclipse.epf.library.layout.elements.ProcessElementItem; import org.eclipse.epf.library.layout.elements.ProcessLayoutData; import org.eclipse.epf.library.layout.elements.SummaryPageLayout; import org.eclipse.epf.library.layout.util.XmlElement; import org.eclipse.epf.library.util.LibraryUtil; import org.eclipse.epf.publishing.PublishingPlugin; import org.eclipse.epf.publishing.PublishingResources; import org.eclipse.epf.publishing.util.PublishingUtil; import org.eclipse.epf.uma.Activity; import org.eclipse.epf.uma.Artifact; import org.eclipse.epf.uma.ContentCategory; import org.eclipse.epf.uma.DeliveryProcess; import org.eclipse.epf.uma.Descriptor; import org.eclipse.epf.uma.Discipline; import org.eclipse.epf.uma.Guidance; import org.eclipse.epf.uma.MethodElement; import org.eclipse.epf.uma.MethodPackage; import org.eclipse.epf.uma.MethodPlugin; import org.eclipse.epf.uma.Practice; import org.eclipse.epf.uma.Process; import org.eclipse.epf.uma.ProcessElement; import org.eclipse.epf.uma.Role; import org.eclipse.epf.uma.SupportingMaterial; import org.eclipse.epf.uma.Task; import org.eclipse.epf.uma.Tool; import org.eclipse.epf.uma.UmaPackage; import org.eclipse.epf.uma.WorkProduct; import org.eclipse.epf.uma.util.AssociationHelper; /** * Builds the views defined for a method configuration. * * @author Shilpa Toraskar * @author Jinhua Xi * @author Kelvin Low * @since 1.0 */ public class ConfigurationViewBuilder extends AbstractViewBuilder { private static final String PREFIX_Reference_Workflows = "Reference_Workflows"; //$NON-NLS-1$ private static final String PREFIX_Tasks = "Tasks"; //$NON-NLS-1$ private static final String PREFIX_ResponsibleFor_Tasks = "Primarily_Performs"; //$NON-NLS-1$ private static final String PREFIX_ParticipatesIn_Tasks = "Additionally_Performs"; //$NON-NLS-1$ private static final String PREFIX_Performing_Roles = "Performing_Roles"; //$NON-NLS-1$ private static final String PREFIX_Input_Work_Products = "Input_Work_Products"; //$NON-NLS-1$ private static final String PREFIX_Output_Work_Products = "Output_Work_Products"; //$NON-NLS-1$ private static final String PREFIX_Work_Products_Created = "Responsible_For"; //$NON-NLS-1$ private static final String PREFIX_Work_Products_Modified = "Modifies"; //$NON-NLS-1$ private static final String PREFIX_Responsible_Role = "Responsible_Role"; //$NON-NLS-1$ private static final String PREFIX_Containing_Work_Product = "Containing_Work_Product"; //$NON-NLS-1$ private static final String PREFIX_Contained_Work_Products = "Contained_Work_Products"; //$NON-NLS-1$ private static final String PREFIX_Guidances = "Guidance"; //$NON-NLS-1$ private static final String PREFIX_InputTo_Task = "Input_to"; //$NON-NLS-1$ private static final String PREFIX_OutputOf_Task = "Output_from"; //$NON-NLS-1$ private static final String ICON_FOLDER = DefaultNodeIconResources .getIconName("folder"); //$NON-NLS-1$ private static final String NODE_Reference_Workflows = PublishingResources.referenceWorkflowsNode_text; //$NON-NLS-1$ private static final String NODE_Tasks = PublishingResources.taskNode_text; //$NON-NLS-1$ private static final String NODE_ResponsibleFor_Tasks = PublishingResources.primarilyPerformsNode_text; //$NON-NLS-1$ private static final String NODE_ParticipatesIn_Tasks = PublishingResources.additionallyPerformsNode_text; //$NON-NLS-1$ private static final String NODE_Performing_Roles = PublishingResources.performingRolesNode_text; //$NON-NLS-1$ private static final String NODE_Input_Work_Products = PublishingResources.inputWorkProductsNode_text; //$NON-NLS-1$ private static final String NODE_Output_Work_Products = PublishingResources.outputWorkProductsNode_text; //$NON-NLS-1$ private static final String NODE_Work_Products_Created = PublishingResources.responsibleForNode_text; //$NON-NLS-1$ private static final String NODE_Work_Products_Modified = PublishingResources.modifiesNode_text; //$NON-NLS-1$ private static final String NODE_Responsible_Role = PublishingResources.responsibleRoleNode_text; //$NON-NLS-1$ private static final String NODE_Containing_Work_Product = PublishingResources.containingWorkProductNode_text; //$NON-NLS-1$ private static final String NODE_Contained_Work_Products = PublishingResources.containedWorkProductsNode_text; //$NON-NLS-1$ private static final String NODE_Guidances = PublishingResources.guidanceNode_text; //$NON-NLS-1$ private static final String NODE_InputTo_Task = PublishingResources.inputToNode_text; //$NON-NLS-1$ private static final String NODE_OutputOf_Task = PublishingResources.outputFromNode_text; //$NON-NLS-1$ private static final String PROCESS_LAYOUT_DATA_FILE = "/scripts/processElementData.js"; //$NON-NLS-1$ private static final Class ITreeItemContentProviderClass = ITreeItemContentProvider.class; protected static boolean debug = PublishingPlugin.getDefault() .isDebugging(); protected List<Bookmark> bookmarks = new ArrayList<Bookmark>(); protected AdapterFactory adapterFactory; protected IProgressMonitor monitor = null; protected EObjectComparator nameComparator = new EObjectComparator(); /** * Creates a new instance. */ public ConfigurationViewBuilder(ISiteGenerator siteGenerator) { super(siteGenerator); } /** * Build the views defined in the configuration and publish the related * contents. * * @param monitor * IProgressMonitor * @return List a list of Bookmarks for the views */ public List<Bookmark> buildViews(IProgressMonitor monitor) { this.monitor = monitor; // System.out.println("Building views..."); //$NON-NLS-1$ long startTime = 0L; if (config != null) { // already done in PublishManager // // first of all, we need to load the library, // // otherwise, some relationships and opposite features are not // // established // monitor.subTask(PublishingResources.loadLibraryTask_name); // if (profiling) { // startTime = System.currentTimeMillis(); // } // LibraryUtil.loadAll((MethodLibrary) config.eContainer()); // if (profiling) { // DebugTrace.print(this, "buildViews", "LibraryUtil.loadAll: " //$NON-NLS-1$ //$NON-NLS-2$ // + (System.currentTimeMillis() - startTime) // + " ms"); //$NON-NLS-1$ // } // create a filter that does not discard the contributors. // so we get the contributors in to show in the navigation tree IFilter configFilter = new ConfigurationFilter(config, false); adapterFactory = TngAdapterFactory.INSTANCE .getConfigurationView_AdapterFactory(configFilter); if (options != null && options.isPublishProcess()) { makeProcessClosure(); } // publish all the views in the configuration if (profiling) { startTime = System.currentTimeMillis(); } List views = LibraryUtil.getValidViews(config); for (Iterator it = views.iterator(); it.hasNext();) { if (monitor.isCanceled()) { return null; } ContentCategory v = (ContentCategory) it.next(); if (!ConfigurationHelper.canShow(v, config)) { continue; } Object element = LibraryUtil.unwrap(v); Bookmark b = createBookmark(this.monitor, element); if (v == config.getDefaultView()) { super.defaultView = b; } // iterate thru configuration to build the view iterate(v, b); if (b.getChildCount() > 0) { bookmarks.add(b); } } if (profiling) { System.out.println("Time taken to publish bookmarks: " //$NON-NLS-1$ + (System.currentTimeMillis() - startTime) + " ms"); //$NON-NLS-1$ } if (monitor.isCanceled()) { return null; } } if (profiling) { startTime = System.currentTimeMillis(); } if (! ConfigurationHelper.serverMode) { publishReferenceElements(); } if (profiling) { DebugTrace.print(this, "publishReferenceElements", //$NON-NLS-1$ (System.currentTimeMillis() - startTime) + " ms"); //$NON-NLS-1$ } // copyIconsForNonApplet(); if (monitor.isCanceled()) { return null; } // save published element urls if (profiling) { startTime = System.currentTimeMillis(); } saveElementUrls(); if (profiling) { DebugTrace.print(this, "saveElementUrls", //$NON-NLS-1$ (System.currentTimeMillis() - startTime) + " ms"); //$NON-NLS-1$ } return bookmarks; } /** * The process element closure is generated as follows: * <p> * 1. publish the selected processses, which brings in all the related * process elements * <p> * 2. publish all the referenced process elements from step 1, this brings * in all the directly referenced content elements. make a first level * closure to include the published elements and the referenced elements. * Any direct references to any type of guidances are also in this closure. * <p> * 3. publish all the referened non-ContentCategory content elements from * step 2. based on the first level closure. The purpose of the first level * closure is to allow bring in guidances with valid element link and any * other references such as a Task or Role, being linked with a missing * element link. This again brings in all the direct references * <p> * 4.Make the final closure by including the following elements: * <p> * a. all published elements from step 1,2,3. * <p> * b. all referenced Guidances from step 3 * <p> * c. all Guidances of type Practice, RoadMap, Suporting Material, and Term * Definition, in the configuration * <p> * d. all Content Categories that contains at least one element of type a, * b, or c. and their parent categories * <p> * The selected view is published based on the element closure defined * above. */ private void makeProcessClosure() { monitor.subTask(PublishingResources.buildingProcessClosureTask_name); // publish the selected processes // need to build a closure of all the elements involved in the // processes List<Process> processes = options.getProcesses(); if (processes != null && processes.size() > 0) { for (Iterator<Process> it = processes.iterator(); it.hasNext();) { makeProcessClosure(it.next()); if (monitor.isCanceled()) { return; } } } // make the first level closure to include all the process elements and // it's referenced elements // any thing except Guidances and ContentCategories outside the closure // is filtered getValidator() .addClosureElements(getValidator().getPublishedElements()); getValidator().addClosureElements( getValidator().getReferencedElements()); // now publish all referenced elements, any direct references in the // process elements are // part of the closure // don't publish content categories for now since they might be empty // and discarded later List refs = new ArrayList(getValidator().getReferencedElements()); for (Iterator it = refs.iterator(); it.hasNext();) { MethodElement e = (MethodElement) it.next(); if (!(e instanceof ContentCategory)) { super.publish(monitor, e); // collect process specific layout info with suppression status // this will incldue the diagrams and the supression states of // each item under the current procee if (LibraryUtil.isProcess(e)) { publishProcessLayout((org.eclipse.epf.uma.Process) e); } } } // now, any referenced guidance should be in the closure, // so include them and make the final closure refs.clear(); for (Iterator it = getValidator().getReferencedElements().iterator(); it .hasNext();) { MethodElement e = (MethodElement) it.next(); if (e instanceof Guidance) { refs.add(e); } } if (refs.size() > 0) { getValidator().addClosureElements(refs); } // now all the published elements are the element closure, make the // final closure getValidator().makeElementClosure(config); } private void makeProcessClosure(org.eclipse.epf.uma.Process proc) { if (proc == null) { return; } if (ConfigurationHelper.canShow(proc, config)) { ActivityLayout l = new ActivityLayout(); l.init(getLayoutMgr(), proc, proc, null); l.findAllLinkedElements(); } if (monitor.isCanceled()) { return; } if (ConfigurationHelper.isExtender(proc)) { org.eclipse.epf.uma.Process baseProc = (org.eclipse.epf.uma.Process) proc .getVariabilityBasedOnElement(); if (ConfigurationHelper.inConfig(baseProc, config)) { makeProcessClosure(baseProc); } } } private void publishReferenceElements() { // now process the referenced elements and publish the contents while (getValidator().getReferencedElements().size() > 0) { MethodElement e = (MethodElement) getValidator() .getReferencedElements().remove(0); try { if (monitor.isCanceled()) { return; } // references to method plugins and method packages can be // ignored if (e instanceof MethodPlugin || e instanceof MethodPackage) { continue; } long startTime = System.currentTimeMillis(); super.publish(monitor, e); // collect process specific layout info with suppression status // this will incldue the diagrams and the supression states of // each item under the current procee if (LibraryUtil.isProcess(e)) { // long startTime1 = System.currentTimeMillis(); publishProcessLayout((org.eclipse.epf.uma.Process) e); // long endTime1 = System.currentTimeMillis(); // System.out.println("Published process " + e.getName() + // ": " + (endTime1 - startTime1) + " ms"); } long endTime = System.currentTimeMillis(); long timeTaken = endTime - startTime; if (timeTaken >= 5000) { System.out.println("Published " + e.getName() + ": " //$NON-NLS-1$ //$NON-NLS-2$ + timeTaken + " ms"); //$NON-NLS-1$ } } catch (Exception ex) { ex.printStackTrace(); getValidator().logError(e, "Error publishing element", ex); //$NON-NLS-1$ } } } private void publishProcessLayout(final org.eclipse.epf.uma.Process e) { Runnable runnable = new Runnable() { public void run() { try { ActivityLayout layout = new ActivityLayout(); layout.init(getLayoutMgr(), (org.eclipse.epf.uma.Process) e, null, null); ProcessLayoutData pd = new ProcessLayoutData(e.getGuid()); layout.loadLayoutData(pd, true, true, true); printLayoutScript(pd); pd.clear(); } catch (Exception e1) { getValidator() .logError( e, "Error publishing process specific layout data", e1); //$NON-NLS-1$ } } }; Timer timer = new Timer(); try { // run the publishing and check the time, if timeout, terminate it Thread t = new Thread(runnable); t.start(); t.join(TIMEOUT_INTERVAL); if (t.isAlive()) { // wait for the thread to die and log an error timer.stop(); getValidator() .logInfo( e, "publishing process specific layout data takes " + timer.getTime() + " mini seconds already and is still not done yet ..."); //$NON-NLS-1$ //$NON-NLS-2$ timer.start(); t.join(); } } catch (InterruptedException e1) { e1.printStackTrace(); } finally { timer.stop(); getValidator() .logInfo( e, timer.getTotalTime() + " mini seconds publishing process specific layout data"); //$NON-NLS-1$ } } private void printLayoutScript(ProcessLayoutData data) { File outputFile = new File(getLayoutMgr().getPublishDir(), PROCESS_LAYOUT_DATA_FILE); //$NON-NLS-1$ PrintWriter pw = null; try { // create a stream with append enabled FileOutputStream os = new FileOutputStream(outputFile, true); // create a write with utf-8 encoding OutputStreamWriter writer = new OutputStreamWriter(os, "utf-8"); //$NON-NLS-1$ // create a print writer with auto flush pw = new PrintWriter(writer, true); data.print(pw); } catch (Exception e) { getValidator().logError("unable to save process layout data", e); //$NON-NLS-1$ } finally { if (pw != null) { pw.flush(); pw.close(); } } } /** * Iterate thru tuee * * @param obj * @param parent */ private void iterate(Object obj, Bookmark parent) { try { if (monitor.isCanceled()) { return; } // Get the adapter from the factory. ITreeItemContentProvider treeItemContentProvider = null; if (obj instanceof ITreeItemContentProvider) { treeItemContentProvider = (ITreeItemContentProvider) obj; } else { treeItemContentProvider = (ITreeItemContentProvider) adapterFactory .adapt(obj, ITreeItemContentProvider.class); } // Either delegate the call or return nothing. if (treeItemContentProvider != null) { Collection items = treeItemContentProvider.getChildren(obj); for (Iterator it = items.iterator(); it.hasNext();) { if (monitor.isCanceled()) { return; } // create bookmark Object itorObj = it.next(); Object element = LibraryUtil.unwrap(itorObj); if ((element instanceof MethodElement)) { MethodElement me = (MethodElement) element; try { if (ConfigurationHelper.canShow(me, config)) { me = ConfigurationHelper .getCalculatedElement(me, getLayoutMgr() .getElementRealizer()); if (me != null) { if (me instanceof Tool) { buildToolSubTree((Tool) me, parent); } else if (me instanceof Discipline) { buildDisciplineSubTree((Discipline) me, parent); } // else if (me instanceof DisciplineGrouping // || me instanceof Domain || me instanceof // WorkProductType // || me instanceof RoleSetGrouping || me // instanceof RoleSet ) else if (me instanceof ContentCategory) { ContentCategory cc = (ContentCategory) me; // if the content category is empty, // don't add to the parent Bookmark b = createBookmark( this.monitor, cc); iterate(itorObj, b); if (options.isPublishEmptyCategories() || b.getChildCount() > 0) { parent.addChild(b); discardEmptyCategory(cc, false); } else { discardEmptyCategory(cc, true); } } else { if (itorObj instanceof PracticeSubgroupItemProvider) { buildPracticeSubgroupTree(obj, parent, (PracticeSubgroupItemProvider) itorObj); } else { Bookmark b = createBookmark(me, parent); if (!buildSubTree(itorObj, me, b)) { iterate(itorObj, b); } } } } } } catch (Exception e) { String message = "Error building navigation tree for " + LibraryUtil.getTypeName(me); //$NON-NLS-1$ getHtmlBuilder().getValidator() .logError(message, e); e.printStackTrace(); } } else { if (itorObj instanceof PracticeSubgroupItemProvider) { buildPracticeSubgroupTree(obj, parent, (PracticeSubgroupItemProvider) itorObj); } else { iterate(itorObj, parent); } } } } } catch (Exception e) { String message = "Error building navigation tree"; //$NON-NLS-1$ getHtmlBuilder().getValidator().logError(message, e); e.printStackTrace(); } } /** * create a bookmark under the specified parent. If no parent is specified, * * @param monitor * @param element * @param parent * @return */ protected Bookmark createBookmark(Object element, Bookmark parent) { Bookmark b = createBookmark(this.monitor, element); if (parent == null) { bookmarks.add(b); } else { parent.addChild(b); } return b; } /** * build the sub tree for the given element. return true if the element is * handled, false otherwise * * @param element * @param bm * @return boolean */ private boolean buildSubTree(Object obj, MethodElement element, Bookmark bm) { boolean isShowRelatedLinks = options.isShowRelatedLinks(); if (element instanceof Task) { if(isShowRelatedLinks) { buildTaskSubTree((Task) element, bm); } else { return true; } } else if (element instanceof Role) { if(isShowRelatedLinks) { buildRoleSubTree((Role) element, bm); } else { return true; } } else if (element instanceof WorkProduct) { if(isShowRelatedLinks) { buildWorkProductSubTree((WorkProduct) element, bm); } else { return true; } } else if (LibraryUtil.isProcess(element)) { buildProcessSubTree(obj, (org.eclipse.epf.uma.Process) element, bm); } else { // System.out.println("Not handled: " + element); return false; } return true; } private void buildItems(List elements, Bookmark bm) { buildItems(elements, bm, false); } private void buildItems(List elements, Bookmark bm, boolean buildSubTree) { for (Iterator it = elements.iterator(); it.hasNext();) { if (monitor.isCanceled()) { return; } MethodElement element = (MethodElement) it.next(); // filter away the containment child-element if any of the parent(s) // are in the list // 00384619 - Published site: Display of WPs under responsible role // if the container of the element is in the list, ignore it if (ConfigurationHelper.isContainmentElement(element) && ConfigurationHelper.isContainerInList(element, elements, config)) { continue; } buildItem(element, bm, buildSubTree); } } private Bookmark buildItem(MethodElement element, Bookmark parent, boolean buildSubTree) { if (monitor.isCanceled()) { return null; } Bookmark b = null; // make sure the element is showable MethodElement e = ConfigurationHelper.getCalculatedElement(element, getLayoutMgr().getElementRealizer()); if (isVisible(e)) { b = createBookmark(this.monitor, e); if (b == null) { return b; } parent.addChild(b); if (buildSubTree) { if (e instanceof Artifact) { buildContainedArtifactsSubTree((Artifact) e, b, true); } } } return b; } // /** // * create the folder bookmark and it's children. generate the folder summary // * page // * // * @param element // * @param bm // * @param nodeName // * @param items // */ // // private Bookmark createFolderBookmark(MethodElement element, Bookmark bm, // String nodeName, List items, boolean createChildren) { // Bookmark b = null; // if (items.size() > 0) { // IElementLayout l = new SummaryPageLayout(getHtmlBuilder() // .getLayoutManager(), element, nodeName, items); // String url = l.getUrl(); // getHtmlBuilder().generateHtml(l); // b = createBookmark(nodeName, EcoreUtil.generateUUID(), url, // ICON_FOLDER, ICON_FOLDER, null); // bm.addChild(b); // if (createChildren) { // buildItems(items, b); // } // } // // return b; // } Set<String> summaryPagesGenerated = new HashSet<String>(); private Bookmark createFolderBookmark(MethodElement element, Bookmark bm, String prefixName, String nodeName, List items, boolean createChildren) { Bookmark b = null; if (items.size() > 0) { IElementLayout l = new SummaryPageLayout(getHtmlBuilder() .getLayoutManager(), element, prefixName, nodeName, items); String url = l.getUrl(); // don't regenerate the page // 200619 - Summary page html was generated multiple times when publishing if ( !summaryPagesGenerated.contains(url) ) { getHtmlBuilder().generateHtml(l); summaryPagesGenerated.add(url); } b = createBookmark(nodeName, EcoreUtil.generateUUID(), url, ICON_FOLDER, ICON_FOLDER, null); bm.addChild(b); if (createChildren) { buildItems(items, b); } } return b; } private void buildPracticeSubgroupTree(Object providerParent, Bookmark parent, PracticeSubgroupItemProvider provider) { Collection children = provider.getChildren(null); List items = children instanceof List ? (List) children : new ArrayList(children); if (items != null && items.size() > 0) { Practice practice = provider.getPractice(); if (practice == null) { return; } IElementLayout l = new SummaryPageLayout(getHtmlBuilder() .getLayoutManager(), practice, provider.getPrefix(), provider.getText(null), items, provider.getText(null)); String url = l.getUrl(); String imageString = this.getNodeIconName(provider); Bookmark b = createBookmark(provider.getText(null), EcoreUtil .generateUUID(), url, imageString, imageString, null); parent.addChild(b); this.iterate(provider, b); if (!summaryPagesGenerated.contains(url)) { getHtmlBuilder().generateHtml(l); summaryPagesGenerated.add(url); } } } private Bookmark buildDisciplineSubTree(Discipline element, Bookmark parent) { String url = ""; //$NON-NLS-1$ Bookmark b; // need to calculate the realized value of the feature List items_workflow = calc0nFeatureValue(element, UmaPackage.eINSTANCE .getDiscipline_ReferenceWorkflows()); // Tasks in published site under Disciplines are in // random order // use the adaptor factory to get the childrens // List items_task = ConfigurationHelper.calc0nFeatureValue(element, // UmaPackage.eINSTANCE.getDiscipline_Tasks(), config); List items_task = new ArrayList(); List item_subDisciplies = new ArrayList(); ITreeItemContentProvider treeItemContentProvider = (ITreeItemContentProvider) adapterFactory .adapt(element, ITreeItemContentProvider.class); if (treeItemContentProvider != null) { Collection items = treeItemContentProvider.getChildren(element); for (Iterator it = items.iterator(); it.hasNext();) { if (monitor.isCanceled()) { return null; } // create bookmark Object itorObj = it.next(); Object e = LibraryUtil.unwrap(itorObj); if ((e instanceof Task)) { MethodElement t = ConfigurationHelper.getCalculatedElement( (MethodElement) e, getLayoutMgr() .getElementRealizer()); if (t != null) { items_task.add(t); } } else if (e instanceof Discipline) { MethodElement d = ConfigurationHelper.getCalculatedElement( (MethodElement) e, getLayoutMgr() .getElementRealizer()); if (d != null) { item_subDisciplies.add(d); } } } } if (monitor.isCanceled()) { return null; } // all guidances List items_guidance = new ArrayList(); items_guidance.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Assets())); items_guidance.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Checklists())); items_guidance.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_ConceptsAndPapers())); items_guidance.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Examples())); items_guidance.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Guidelines())); items_guidance.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_SupportingMaterials())); if (!options.isPublishEmptyCategories() && items_workflow.size() + items_task.size() + items_guidance.size() + item_subDisciplies.size() == 0) { // do nothing, don't show the folder discardEmptyCategory(element, true); return null; } if (monitor.isCanceled()) { return null; } // create the item bookmark // don't set to the parent yet. make sure it's not empty // need to check the sub-disciplines // 150984 - Publishing: Nested discipline is not display in the publish // page // Bookmark bm = createBookmark(element, parent); Bookmark bm = createBookmark(this.monitor, element); // sub-disciplines come first if (item_subDisciplies.size() > 0) { for (Iterator it = item_subDisciplies.iterator(); it.hasNext();) { Discipline d = (Discipline) it.next(); buildDisciplineSubTree(d, bm); } } if (options.isPublishLightWeightTree()) { Collections.sort(items_workflow, nameComparator); //Collections.sort(items_task, nameComparator); Collections.sort(items_guidance, nameComparator); buildItems(items_workflow, bm); buildItems(items_task, bm); buildItems(items_guidance, bm); } else { if (items_workflow.size() > 0) { Bookmark wfFolder = createFolderBookmark(element, bm, PREFIX_Reference_Workflows, NODE_Reference_Workflows, items_workflow, false); // Capability Patterns in treebrowser under // disciplines-reference workflows cannot be expanded for (Iterator it = items_workflow.iterator(); it.hasNext();) { if (monitor.isCanceled()) { return null; } // 179609 - Exception when assign activity as discipline's // referenced workflow // this is a model change, referenced workflow can be // Activity, // old model references Process Activity act = (Activity) it.next(); Bookmark bmWorkflow = buildItem(act, wfFolder, false); buildActivitySubTree(act, act, bmWorkflow); } } if (monitor.isCanceled()) { return null; } if (items_task.size() > 0) { createFolderBookmark(element, bm, PREFIX_Tasks, NODE_Tasks, items_task, true); } if (monitor.isCanceled()) { return null; } if (items_guidance.size() > 0) { createFolderBookmark(element, bm, PREFIX_Guidances, NODE_Guidances, items_guidance, true); } } if (options.isPublishEmptyCategories() || bm.getChildCount() > 0) { parent.addChild(bm); discardEmptyCategory(element, false); } else { discardEmptyCategory(element, true); } return bm; } private void buildActivitySubTree(Object obj, Activity element, Bookmark bm) { if (monitor.isCanceled()) { return; } List items = new ArrayList(); org.eclipse.epf.uma.Process proc = TngUtil.getOwningProcess(element); ProcessElementItem procItem = new ProcessElementItem(obj, element, element.getGuid()); ComposedAdapterFactory adapterFactory = super.getLayoutMgr() .getWBSAdapterFactory(); Suppression sup = new Suppression(proc); iterateActivity(procItem, bm, adapterFactory, sup); } private void buildToolSubTree(Tool element, Bookmark parent) { if (monitor.isCanceled()) { return; } List items = calc0nFeatureValue(element, UmaPackage.eINSTANCE .getTool_ToolMentors()); if (options.isPublishEmptyCategories() || items.size() > 0) { Bookmark b = createBookmark(element, parent); buildItems(items, b); discardEmptyCategory(element, false); } else { discardEmptyCategory(element, true); } } private void buildTaskSubTree(Task element, Bookmark bm) { String url; Bookmark b; List allItems = new ArrayList(); // performing roles List items = new ArrayList(); List rList = (List) calc0nFeatureValue(element, UmaPackage.eINSTANCE .getTask_PerformedBy()); if (rList != null) { items.addAll(rList); } items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getTask_AdditionallyPerformedBy())); if (items.size() > 0) { if (options.isPublishLightWeightTree()) { Collections.sort(items, nameComparator); allItems.addAll(items); } else { createFolderBookmark(element, bm, PREFIX_Performing_Roles, NODE_Performing_Roles, items, true); } } if (monitor.isCanceled()) { return; } if (!options.isPublishLightWeightTree()) { // input work products, need a summary page, items = new ArrayList(); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getTask_MandatoryInput())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getTask_OptionalInput())); if (items.size() > 0) { createFolderBookmark(element, bm, PREFIX_Input_Work_Products, NODE_Input_Work_Products, items, true); } if (monitor.isCanceled()) { return; } } // output work products, need a summary page, TODO items = calc0nFeatureValue(element, UmaPackage.eINSTANCE .getTask_Output()); if (items.size() > 0) { if (options.isPublishLightWeightTree()) { Collections.sort(items, nameComparator); allItems.addAll(items); } else { createFolderBookmark(element, bm, PREFIX_Output_Work_Products, NODE_Output_Work_Products, items, true); } } if (monitor.isCanceled()) { return; } // all guidances items.clear(); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Assets())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Checklists())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_ConceptsAndPapers())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Examples())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Guidelines())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_SupportingMaterials())); // Object e = calc01FeatureValue(element, UmaPackage.eINSTANCE // .getTask_Estimate()); // if (e != null) { // items.add(e); // } items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getTask_ToolMentors())); if (items.size() > 0) { if (options.isPublishLightWeightTree()) { Collections.sort(items, nameComparator); allItems.addAll(items); } else { createFolderBookmark(element, bm, PREFIX_Guidances, NODE_Guidances, items, true); } } if (options.isPublishLightWeightTree()) { buildItems(allItems, bm); } } private void buildRoleSubTree(Role element, Bookmark bm) { String url; Bookmark b; if (monitor.isCanceled()) { return; } List allItems = new ArrayList(); // tasks, // need a general overview page, TODO // List items = AssociationHelper.getPrimaryTasks(element); List items = calc0nFeatureValue(element, AssociationHelper.Role_Primary_Tasks); if (items.size() > 0) { if (options.isPublishLightWeightTree()) { Collections.sort(items, nameComparator); allItems.addAll(items); } else { createFolderBookmark(element, bm, PREFIX_ResponsibleFor_Tasks, NODE_ResponsibleFor_Tasks, items, true); } } if (monitor.isCanceled()) { return; } if (!options.isPublishLightWeightTree()) { // secondary tasks items = calc0nFeatureValue(element, AssociationHelper.Role_Secondary_Tasks); if (items.size() > 0) { createFolderBookmark(element, bm, PREFIX_ParticipatesIn_Tasks, NODE_ParticipatesIn_Tasks, items, true); } } if (monitor.isCanceled()) { return; } // responsible for work products, items = calc0nFeatureValue(element, UmaPackage.eINSTANCE .getRole_ResponsibleFor()); if (items.size() > 0) { if (options.isPublishLightWeightTree()) { Collections.sort(items, nameComparator); allItems.addAll(items); } else { b = createFolderBookmark(element, bm, PREFIX_Work_Products_Created, NODE_Work_Products_Created, items, false); buildItems(items, b, true); } } if (monitor.isCanceled()) { return; } if (!options.isPublishLightWeightTree()) { // modifies work products, need a summary page, TODO items = calc0nFeatureValue(element, UmaPackage.eINSTANCE .getRole_Modifies()); if (items.size() > 0) { b = createFolderBookmark(element, bm, PREFIX_Work_Products_Modified, NODE_Work_Products_Modified, items, false); buildItems(items, b, true); } if (monitor.isCanceled()) { return; } } // all guidances items.clear(); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Assets())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Checklists())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_ConceptsAndPapers())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Examples())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Guidelines())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_SupportingMaterials())); if (items.size() > 0) { if (options.isPublishLightWeightTree()) { Collections.sort(items, nameComparator); allItems.addAll(items); } else { createFolderBookmark(element, bm, PREFIX_Guidances, NODE_Guidances, items, true); } } if (options.isPublishLightWeightTree()) { // light weight tree, no sub folders buildItems(allItems, bm); } } private void buildWorkProductSubTree(WorkProduct element, Bookmark bm) { List items; String url = ""; //$NON-NLS-1$ // Bookmark b; if (monitor.isCanceled()) { return; } List allItems = new ArrayList(); // performing roles, 0.1 reference element will be realized in buildItem // multiplicity change for opposite features // Role r = AssociationHelper.getResponsibleRole(element); items = calc0nFeatureValue(element, AssociationHelper.WorkProduct_ResponsibleRoles); if (items.size() > 0) { if (options.isPublishLightWeightTree()) { Collections.sort(items, nameComparator); allItems.addAll(items); } else { createFolderBookmark(element, bm, PREFIX_Responsible_Role, NODE_Responsible_Role, items, true); } } if (monitor.isCanceled()) { return; } // containing work products, need a summary page, TODO if (element instanceof Artifact) { if (!options.isPublishLightWeightTree()) { WorkProduct wp = ((Artifact) element).getContainerArtifact(); // createBookmark(NODE_Containing_Work_Product, // NODE_Containing_Work_Product, url, "", ""); //$NON-NLS-1$ // //$NON-NLS-2$ if (wp != null) { items = new ArrayList(); items.add(wp); createFolderBookmark(element, bm, PREFIX_Containing_Work_Product, NODE_Containing_Work_Product, items, true); } if (monitor.isCanceled()) { return; } } // contained work products, need a summary page, TODO // items = ((Artifact)element).getContainedArtifacts(); items = calc0nFeatureValue(element, UmaPackage.eINSTANCE .getArtifact_ContainedArtifacts()); // make sure the contained elements does not contain the container, // this is possible due to realization, say, the containing element // contribute to the container items.remove(element); if (items.size() > 0) { if (options.isPublishLightWeightTree()) { Collections.sort(items, nameComparator); allItems.addAll(items); } else { Bookmark b = createFolderBookmark(element, bm, PREFIX_Contained_Work_Products, NODE_Contained_Work_Products, items, false); // for each contained work product, create the nested sub // tree buildItems(items, b, true); } } } if (monitor.isCanceled()) { return; } if (!options.isPublishLightWeightTree()) { // input to tasks items = new ArrayList(); items.addAll(calc0nFeatureValue(element, AssociationHelper.WorkProduct_MandatoryInputTo_Tasks)); items.addAll(calc0nFeatureValue(element, AssociationHelper.WorkProduct_OptionalInputTo_Tasks)); if (items.size() > 0) { createFolderBookmark(element, bm, PREFIX_InputTo_Task, NODE_InputTo_Task, items, true); } if (monitor.isCanceled()) { return; } // output from tasks items = calc0nFeatureValue(element, AssociationHelper.WorkProduct_OutputFrom_Tasks); if (items.size() > 0) { createFolderBookmark(element, bm, PREFIX_OutputOf_Task, NODE_OutputOf_Task, items, true); } if (monitor.isCanceled()) { return; } } // all guidances items = new ArrayList(); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Assets())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Checklists())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_ConceptsAndPapers())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Examples())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Guidelines())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_SupportingMaterials())); // Object e = calc01FeatureValue(element, UmaPackage.eINSTANCE // .getWorkProduct_Estimate()); // if (e != null) { // items.add(e); // } items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getWorkProduct_Reports())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getWorkProduct_Templates())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getWorkProduct_ToolMentors())); if (items.size() > 0) { if (options.isPublishLightWeightTree()) { Collections.sort(items, nameComparator); allItems.addAll(items); } else { createFolderBookmark(element, bm, PREFIX_Guidances, NODE_Guidances, items, true); } } if (options.isPublishLightWeightTree()) { buildItems(allItems, bm); } } private void buildContainedArtifactsSubTree(Artifact element, Bookmark bm, boolean showGuidances) { if (monitor.isCanceled()) { return; } List items; String url = ""; //$NON-NLS-1$ // contained work products, need a summary page, TODO // items = ((Artifact)element).getContainedArtifacts(); items = calc0nFeatureValue(element, UmaPackage.eINSTANCE .getArtifact_ContainedArtifacts()); // make sure the contained elements does not contain the container, // this is possible due to realization, say, the containing element // contribute to the container items.remove(element); if (monitor.isCanceled()) { return; } if (items.size() > 0) { // Bookmark b = createFolderBookmark(element, bm, // NODE_Contained_Work_Products, items, false); // for each contained work product, create the nested sub tree for (Iterator it = items.iterator(); it.hasNext();) { if (monitor.isCanceled()) { return; } Artifact e = (Artifact) it.next(); buildItem(e, bm, true); } } if (!showGuidances) { return; } if (monitor.isCanceled()) { return; } // all guidances items = new ArrayList(); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Assets())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Checklists())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_ConceptsAndPapers())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Examples())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_Guidelines())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getContentElement_SupportingMaterials())); // Object e = calc01FeatureValue(element, UmaPackage.eINSTANCE // .getWorkProduct_Estimate()); // if (e != null) { // items.add(e); // } items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getWorkProduct_Reports())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getWorkProduct_Templates())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getWorkProduct_ToolMentors())); if (items.size() > 0) { // createFolderBookmark(element, bm, NODE_Guidances, items, true); buildItems(items, bm); } } /** * iterate the break down structure and build the xml document * * @param parentObj * The object to iterate. It can be a breakdown element, or it's * adaptor * @param parentXml * @param adapterFactory */ private void iterateActivity(ProcessElementItem parentItem, Bookmark parentBm, ComposedAdapterFactory adapterFactory, Suppression sup) { if (monitor.isCanceled()) { return; } ITreeItemContentProvider provider = null; Object parentObj = parentItem.rawItem; if (parentObj instanceof ITreeItemContentProvider) { provider = (ITreeItemContentProvider) parentObj; } else { provider = (ITreeItemContentProvider) adapterFactory.adapt( parentObj, ITreeItemContentProvider.class); } if (provider != null) { // String displayName = ProcessUtil.getAttribute(parentObj, // IBSItemProvider.COL_PRESENTATION_NAME, provider); // parentXml.setAttribute("DisplayName", displayName); Collection children = provider.getChildren(parentObj); for (Iterator it = children.iterator(); it.hasNext();) { if (monitor.isCanceled()) { return; } Object rawitem = it.next(); if (sup.isSuppressed(rawitem)) { continue; } MethodElement item = (MethodElement) LibraryUtil .unwrap(rawitem); if (!options.showDescriptorsInNavigationTree && (item instanceof Descriptor)) { continue; } ProcessElementItem elementItem = new ProcessElementItem( rawitem, item, parentItem); Bookmark child = buildItem(elementItem.element, parentBm, false); if (child != null) { // set the query string child.setQueryString(elementItem.getQueryString()); IBSItemProvider adapter = null; if (rawitem instanceof IBSItemProvider) { adapter = (IBSItemProvider) rawitem; } else { adapter = (IBSItemProvider) adapterFactory.adapt(item, ITreeItemContentProvider.class); ; } String displayName = ProcessUtil.getAttribute(item, IBSItemProvider.COL_PRESENTATION_NAME, adapter); child.setPresentationName(displayName); if (item instanceof Activity) { iterateActivity(elementItem, child, adapterFactory, sup); } } } } } private void buildProcessSubTree(Object obj, org.eclipse.epf.uma.Process element, Bookmark bm) { if (monitor.isCanceled()) { return; } List items = new ArrayList(); ProcessElementItem procItem = new ProcessElementItem(obj, element, element.getGuid()); ComposedAdapterFactory adapterFactory = super.getLayoutMgr() .getWBSAdapterFactory(); Suppression sup = new Suppression(element); iterateActivity(procItem, bm, adapterFactory, sup); String url; Bookmark b; if (monitor.isCanceled()) { return; } // all guidances items = new ArrayList(); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getBreakdownElement_Checklists())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getBreakdownElement_Concepts())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getBreakdownElement_Examples())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getBreakdownElement_Guidelines())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getBreakdownElement_ReusableAssets())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getActivity_Roadmaps())); // need to include supporting materials as well // fix bug: supporting material served as user defined diagram should not // show up in the navigation tree of a published process. org.eclipse.epf.diagram.model.util.DiagramInfo userDiagramInfo = new org.eclipse.epf.diagram.model.util.DiagramInfo(element); List v = calc0nFeatureValue(element, UmaPackage.eINSTANCE .getBreakdownElement_SupportingMaterials()); for ( Iterator it = v.iterator(); it.hasNext(); ) { SupportingMaterial s = (SupportingMaterial)it.next(); if ( !userDiagramInfo.isDiagram( (SupportingMaterial)s ) ) { items.add(s); } } if (element instanceof DeliveryProcess) { DeliveryProcess dp = (DeliveryProcess) element; items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getDeliveryProcess_CommunicationsMaterials())); items.addAll(calc0nFeatureValue(element, UmaPackage.eINSTANCE .getDeliveryProcess_EducationMaterials())); } if (items.size() > 0) { createFolderBookmark(element, bm, PREFIX_Guidances, NODE_Guidances, items, true); } } /** * dispose the object */ public void dispose() { super.dispose(); adapterFactory = null; nameComparator = null; bookmarks.clear(); elementUrls.clear(); summaryPagesGenerated.clear(); } protected Set elementUrls = new HashSet(); protected void elementPublished(IElementLayout layout, String htmlfile) { // only for process element for now // may cover all method elements later if (layout.getElement() instanceof ProcessElement) { ElementUrl url = new ElementUrl(layout.getElement().getGuid(), layout.getUrl(), layout.getDisplayName()); elementUrls.add(url); } } private void saveElementUrls() { // save published element urls // need to escape the url and text since it will be assigned to a // javascript variable as literal XmlElement xml = new XmlElement("ElementUrls"); //$NON-NLS-1$ for (Iterator it = elementUrls.iterator(); it.hasNext();) { ElementUrl url = (ElementUrl) it.next(); xml.newChild("elementUrl", url.guid) //$NON-NLS-1$ .setAttribute("text", StrUtil.escape(url.text)) //$NON-NLS-1$ .setAttribute("url", StrUtil.escape(url.url)); //$NON-NLS-1$ } // StringBuffer buffer = new StringBuffer(); // buffer.append(XmlHelper.XML_HEADER).append(xml.toXml()); // File f = new File(getLayoutMgr().getPublishDir(), "ElementUrls.xml"); // //$NON-NLS-1$ // FileUtil.writeUTF8File(f.getAbsolutePath(), buffer.toString()); String html = PublishingUtil.getHtml(xml, "xsl/elementUrls.xsl"); //$NON-NLS-1$ File f = new File(getLayoutMgr().getPublishDir(), PROCESS_LAYOUT_DATA_FILE); //$NON-NLS-1$ FileUtil.writeUTF8File(f.getAbsolutePath(), html, true); } /** * data structure to define url of an element * * @author Jinhua Xi * */ public class ElementUrl { String guid; String url; String text; /** * constructor * * @param guid * String the guid of the element * @param url * String the url of the element * @param text * String the text alone with the url */ public ElementUrl(String guid, String url, String text) { this.guid = guid; this.url = url; this.text = text; } } class EObjectComparator implements Comparator { private EStructuralFeature pName = UmaPackage.eINSTANCE .getMethodElement_PresentationName(); private EStructuralFeature name = UmaPackage.eINSTANCE .getNamedElement_Name(); public EObjectComparator() { } public int compare(Object e1, Object e2) { if (e1 instanceof EObject && e2 instanceof EObject) { Object v1 = getValue(e1); Object v2 = getValue(e2); if (v1 == null && v2 == null) { return e1.toString().compareTo(e2.toString()); } else if (v1 == null) { return -1; } else if (v2 == null) { return 1; } else { return v1.toString().compareTo(v2.toString()); } } else { return e1.toString().compareTo(e2.toString()); } } private Object getValue(Object e) { Object v = null; try { v = ((EObject) e).eGet(pName); } catch (Exception ex) { } ; if (v == null || v.toString().length() == 0) { try { v = ((EObject) e).eGet(name); } catch (Exception ex) { } ; } return v; } } }