Coverage Report - org.kuali.student.lum.lu.ui.course.client.controllers.ViewCourseController
 
Classes in this File Line Coverage Branch Coverage Complexity
ViewCourseController
0%
0/135
0%
0/38
1.717
ViewCourseController$1
0%
0/6
0%
0/2
1.717
ViewCourseController$1$1
0%
0/8
0%
0/6
1.717
ViewCourseController$10
0%
0/3
N/A
1.717
ViewCourseController$2
0%
0/6
0%
0/2
1.717
ViewCourseController$3
0%
0/9
N/A
1.717
ViewCourseController$4
0%
0/15
0%
0/10
1.717
ViewCourseController$5
0%
0/12
N/A
1.717
ViewCourseController$5$1
0%
0/4
0%
0/2
1.717
ViewCourseController$6
0%
0/12
N/A
1.717
ViewCourseController$7
0%
0/5
0%
0/2
1.717
ViewCourseController$8
0%
0/3
N/A
1.717
ViewCourseController$9
0%
0/3
N/A
1.717
 
 1  
 /**
 2  
  * Copyright 2010 The Kuali Foundation Licensed under the
 3  
  * Educational Community License, Version 2.0 (the "License"); you may
 4  
  * not use this file except in compliance with the License. You may
 5  
  * obtain a copy of the License at
 6  
  *
 7  
  * http://www.osedu.org/licenses/ECL-2.0
 8  
  *
 9  
  * Unless required by applicable law or agreed to in writing,
 10  
  * software distributed under the License is distributed on an "AS IS"
 11  
  * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 12  
  * or implied. See the License for the specific language governing
 13  
  * permissions and limitations under the License.
 14  
  */
 15  
 
 16  
 package org.kuali.student.lum.lu.ui.course.client.controllers;
 17  
 
 18  
 import java.util.ArrayList;
 19  
 import java.util.List;
 20  
 
 21  
 import org.kuali.student.common.assembly.data.Data;
 22  
 import org.kuali.student.common.assembly.data.Metadata;
 23  
 import org.kuali.student.common.dto.DtoConstants;
 24  
 import org.kuali.student.common.rice.authorization.PermissionType;
 25  
 import org.kuali.student.common.ui.client.application.Application;
 26  
 import org.kuali.student.common.ui.client.application.KSAsyncCallback;
 27  
 import org.kuali.student.common.ui.client.application.ViewContext;
 28  
 import org.kuali.student.common.ui.client.configurable.mvc.layouts.DocumentLayoutController;
 29  
 import org.kuali.student.common.ui.client.configurable.mvc.layouts.TabMenuController;
 30  
 import org.kuali.student.common.ui.client.configurable.mvc.views.SectionView;
 31  
 import org.kuali.student.common.ui.client.mvc.Callback;
 32  
 import org.kuali.student.common.ui.client.mvc.DataModel;
 33  
 import org.kuali.student.common.ui.client.mvc.DataModelDefinition;
 34  
 import org.kuali.student.common.ui.client.mvc.ModelProvider;
 35  
 import org.kuali.student.common.ui.client.mvc.ModelRequestCallback;
 36  
 import org.kuali.student.common.ui.client.mvc.View;
 37  
 import org.kuali.student.common.ui.client.mvc.WorkQueue;
 38  
 import org.kuali.student.common.ui.client.mvc.WorkQueue.WorkItem;
 39  
 import org.kuali.student.common.ui.client.mvc.dto.ReferenceModel;
 40  
 import org.kuali.student.common.ui.client.util.ExportElement;
 41  
 import org.kuali.student.common.ui.client.util.ExportUtils;
 42  
 import org.kuali.student.common.ui.client.util.WindowTitleUtils;
 43  
 import org.kuali.student.common.ui.client.widgets.KSButton;
 44  
 import org.kuali.student.common.ui.client.widgets.KSLabel;
 45  
 import org.kuali.student.common.ui.client.widgets.KSLightBox;
 46  
 import org.kuali.student.common.ui.client.widgets.KSButtonAbstract.ButtonStyle;
 47  
 import org.kuali.student.common.ui.client.widgets.notification.KSNotification;
 48  
 import org.kuali.student.common.ui.client.widgets.notification.KSNotifier;
 49  
 import org.kuali.student.common.ui.client.widgets.progress.BlockingTask;
 50  
 import org.kuali.student.common.ui.client.widgets.progress.KSBlockingProgressIndicator;
 51  
 import org.kuali.student.common.ui.client.widgets.table.summary.SummaryTableSection;
 52  
 import org.kuali.student.common.ui.shared.IdAttributes.IdType;
 53  
 import org.kuali.student.core.statement.dto.StatementTypeInfo;
 54  
 import org.kuali.student.lum.common.client.helpers.RecentlyViewedHelper;
 55  
 import org.kuali.student.lum.lu.ui.course.client.configuration.CourseConfigurer;
 56  
 import org.kuali.student.lum.lu.ui.course.client.configuration.ViewCourseConfigurer;
 57  
 import org.kuali.student.lum.lu.ui.course.client.configuration.CourseConfigurer.CourseSections;
 58  
 import org.kuali.student.lum.lu.ui.course.client.configuration.ViewCourseConfigurer.ViewCourseSections;
 59  
 import org.kuali.student.lum.lu.ui.course.client.requirements.CourseRequirementsDataModel;
 60  
 import org.kuali.student.lum.lu.ui.course.client.requirements.HasRequirements;
 61  
 import org.kuali.student.lum.lu.ui.course.client.service.CourseRpcService;
 62  
 import org.kuali.student.lum.lu.ui.course.client.service.CourseRpcServiceAsync;
 63  
 import org.kuali.student.lum.lu.ui.course.client.widgets.CourseWorkflowActionList;
 64  
 
 65  
 import com.google.gwt.core.client.GWT;
 66  
 import com.google.gwt.event.dom.client.ClickEvent;
 67  
 import com.google.gwt.event.dom.client.ClickHandler;
 68  
 import com.google.gwt.event.logical.shared.CloseEvent;
 69  
 import com.google.gwt.event.logical.shared.CloseHandler;
 70  
 import com.google.gwt.user.client.Window;
 71  
 import com.google.gwt.user.client.ui.Widget;
 72  
 
 73  
 /**
 74  
  * This is a description of what this class does - Will Gomes don't forget to fill this in. 
 75  
  * 
 76  
  * @author Kuali Student Team
 77  
  *
 78  
  */
 79  0
 public class ViewCourseController extends TabMenuController implements DocumentLayoutController, HasRequirements{
 80  0
     private final DataModel cluModel = new DataModel(); 
 81  
    
 82  
     private WorkQueue modelRequestQueue;
 83  
 
 84  0
     private String cluType = "kuali.lu.type.CreditCourse";
 85  0
     private String courseId = null;
 86  
     
 87  
     private static final String CLU_STATE = DtoConstants.STATE_ACTIVE;
 88  
     private static final String MSG_GROUP = "course";
 89  
     
 90  0
     private final String REFERENCE_TYPE = "referenceType.clu";
 91  0
     private boolean initialized = false;
 92  0
     CourseRpcServiceAsync rpcServiceAsync = GWT.create(CourseRpcService.class);
 93  
     
 94  0
         private final BlockingTask loadDataTask = new BlockingTask("Retrieving Data....");
 95  0
         private final BlockingTask initTask = new BlockingTask("Initializing....");
 96  0
         private final KSLabel statusLabel = new KSLabel("");
 97  
         
 98  0
         private final List<CourseWorkflowActionList> actionDropDownWidgets = new ArrayList<CourseWorkflowActionList>();
 99  
 
 100  
     private final CourseRequirementsDataModel reqDataModel;
 101  
     
 102  0
     final ViewCourseConfigurer cfg = GWT.create(ViewCourseConfigurer.class);
 103  
                     
 104  
     public ViewCourseController(Enum<?> viewType){
 105  0
             super(CourseProposalController.class.getName());
 106  0
         initialize();
 107  0
         addStyleName("courseView");
 108  0
         reqDataModel = new CourseRequirementsDataModel(this);
 109  0
         this.tabPanel.addStyleName("standard-content-padding");
 110  0
         this.setViewEnum(viewType);
 111  0
     }
 112  
     
 113  
     @Override
 114  
     public void setViewContext(ViewContext viewContext) {
 115  0
             super.setViewContext(viewContext);
 116  0
             if(viewContext.getId() != null && !viewContext.getId().isEmpty()){
 117  0
                     viewContext.setPermissionType(PermissionType.OPEN);
 118  0
                     this.setCourseId(viewContext.getId());
 119  
             }
 120  0
     }
 121  
     
 122  
     private void initialize() {
 123  0
         super.setDefaultModelId(CourseConfigurer.CLU_PROPOSAL_MODEL);
 124  0
         super.registerModel(CourseConfigurer.CLU_PROPOSAL_MODEL, new ModelProvider<DataModel>() {
 125  
 
 126  
             @Override
 127  
             public void requestModel(final ModelRequestCallback<DataModel> callback) {
 128  0
                 if (modelRequestQueue == null){
 129  0
                     modelRequestQueue = new WorkQueue();
 130  
                 }
 131  
 
 132  0
                 WorkItem workItem = new WorkItem(){
 133  
                     @Override
 134  
                     public void exec(Callback<Boolean> workCompleteCallback) {
 135  0
                         if (cluModel.getRoot() == null || cluModel.getRoot().size() == 0){
 136  0
                             if (courseId != null){
 137  0
                                 getCourseFromCluId(callback, workCompleteCallback);
 138  
                             } else{
 139  0
                                 createNewCluModel(callback, workCompleteCallback);
 140  
                             }                
 141  
                         } else {
 142  0
                             callback.onModelReady(cluModel);
 143  0
                             workCompleteCallback.exec(true);
 144  
                         }
 145  0
                     }               
 146  
                 };
 147  0
                 modelRequestQueue.submit(workItem);
 148  
                 
 149  0
             }
 150  
             
 151  
         });
 152  
         
 153  
             
 154  0
     }
 155  
     
 156  
      
 157  
     public Widget generateActionDropDown(){                            
 158  0
             CourseWorkflowActionList actionList = new CourseWorkflowActionList(this.getMessage("cluActionsLabel"), getViewContext(), "/HOME/CURRICULUM_HOME/COURSE_PROPOSAL", cluModel, new Callback<String>() {
 159  
                     @Override
 160  
                     public void exec(String newState) {
 161  0
                             if (newState != null) {
 162  0
                     KSNotifier.add(new KSNotification(getMessage("cluStateChangeNotification" + newState), false, 5000));
 163  
                     // FIXME: this is not updating the cluModel so state will not be updated in the model.  May not be a problem.
 164  0
                     statusLabel.setText("Status: " + newState);
 165  
                             } else {
 166  0
                     KSNotifier.add(new KSNotification(getMessage("cluStateChangeFailedNotification"), false, 5000));
 167  
                             }
 168  0
                     }
 169  
             });
 170  0
         actionDropDownWidgets.add(actionList);
 171  
         
 172  0
             return actionList;
 173  
     }
 174  
    
 175  
     private void init(final Callback<Boolean> onReadyCallback) {
 176  
 
 177  0
         if (initialized) {
 178  0
             onReadyCallback.exec(true);
 179  
         } else {
 180  0
                 KSBlockingProgressIndicator.addTask(initTask);
 181  0
                 this.setContentTitle("View Course");
 182  0
                     this.setName("Course");
 183  0
                     String idType = null;
 184  0
                     String viewContextId = null;
 185  
                     // The switch was added due to the way permissions currently work.
 186  
                     // For a new Create Course Proposal or Modify Course we send nulls so that permissions are not checked.
 187  0
                     if(getViewContext().getIdType() != null){
 188  0
                 idType = getViewContext().getIdType().toString();
 189  0
                 viewContextId = getViewContext().getId();
 190  0
                 if(getViewContext().getIdType()==IdType.COPY_OF_OBJECT_ID){
 191  0
                         viewContextId = null;
 192  
                 }
 193  
 
 194  
                     }
 195  
                     
 196  0
                 rpcServiceAsync.getMetadata("", null, new KSAsyncCallback<Metadata>(){
 197  
 
 198  
                         @Override
 199  
                 public void handleFailure(Throwable caught) {
 200  0
                                 initialized = false;
 201  0
                         onReadyCallback.exec(false);
 202  0
                         KSBlockingProgressIndicator.removeTask(initTask);
 203  0
                     throw new RuntimeException("Failed to get model definition.", caught);
 204  
                 }
 205  
 
 206  
                 public void onSuccess(Metadata result) {
 207  0
                         DataModelDefinition def = new DataModelDefinition(result);
 208  0
                     cluModel.setDefinition(def);
 209  0
                     init(def, onReadyCallback);
 210  0
                 }
 211  
                   });
 212  
             
 213  
         }
 214  0
     }
 215  
 
 216  
     private void updateCourseActionItems() {
 217  
             
 218  0
                 for(CourseWorkflowActionList widget: actionDropDownWidgets){
 219  0
                         widget.updateCourseActionItems(cluModel);
 220  0
                         widget.setEnabled(true);
 221  0
                         if(widget.isEmpty()) {
 222  0
                                 widget.setVisible(false);
 223  
                         }
 224  
                         else{
 225  0
                                 widget.setVisible(true);
 226  
                         }
 227  
                 }
 228  0
     }
 229  
 
 230  
     private void init(final DataModelDefinition modelDefinition, final Callback<Boolean> onReadyCallback){
 231  
 
 232  0
         CourseRequirementsDataModel.getStatementTypes(new Callback<List<StatementTypeInfo>>() {
 233  
 
 234  
             @Override
 235  
             public void exec(List<StatementTypeInfo> stmtTypes) {
 236  0
                 List<StatementTypeInfo> stmtTypesOut = new ArrayList<StatementTypeInfo>();
 237  0
                 if (stmtTypes != null) {
 238  0
                     for (StatementTypeInfo stmtType : stmtTypes) {
 239  0
                         if (stmtType.getId().contains("kuali.statement.type.course.enrollmentEligibility") ||
 240  
                             stmtType.getId().contains("kuali.statement.type.course.creditConstraints")) {
 241  0
                             continue;
 242  
                         }
 243  0
                         stmtTypesOut.add(stmtType);
 244  
                     }
 245  
                 }
 246  0
                 if(!initialized){
 247  0
                         initialized = true;
 248  0
                         cfg.setStatementTypes(stmtTypesOut);
 249  0
                         cfg.setModelDefinition(modelDefinition);
 250  0
                         cfg.generateLayout(ViewCourseController.this);
 251  
                 }
 252  0
                 onReadyCallback.exec(true);
 253  0
                 KSBlockingProgressIndicator.removeTask(initTask);
 254  0
             }
 255  
         });
 256  0
     }
 257  
     
 258  
     @SuppressWarnings("unchecked")
 259  
     @Override
 260  
     public void requestModel(Class modelType, final ModelRequestCallback callback) {
 261  0
         if(modelType == ReferenceModel.class){
 262  0
             if (cluModel != null){
 263  0
                 ReferenceModel ref = new ReferenceModel();
 264  
 
 265  0
                 if(cluModel.get("course/id") != null){
 266  0
                     ref.setReferenceId((String)cluModel.get("course/id"));
 267  
                 } else{
 268  0
                     ref.setReferenceId(null);
 269  
                 }
 270  
                 
 271  0
                 ref.setReferenceTypeKey(REFERENCE_TYPE);
 272  0
                 ref.setReferenceType(cluType);
 273  0
                 ref.setReferenceState(CLU_STATE);
 274  
                 
 275  0
                 callback.onModelReady(ref);
 276  0
             }
 277  0
         }else if (modelType == Data.class){
 278  0
             requestModel(CourseConfigurer.CLU_PROPOSAL_MODEL, callback);
 279  
         } else {
 280  0
             super.requestModel(modelType, callback);
 281  
         }
 282  0
     }
 283  
        
 284  
     @SuppressWarnings("unchecked")    
 285  
     private void getCourseFromCluId(final ModelRequestCallback callback, final Callback<Boolean> workCompleteCallback){
 286  0
             KSBlockingProgressIndicator.addTask(loadDataTask);
 287  
 
 288  0
         rpcServiceAsync.getData(courseId, new KSAsyncCallback<Data>(){
 289  
 
 290  
             @Override
 291  
             public void handleFailure(Throwable caught) {
 292  0
                 Window.alert("Error loading Course: "+caught.getMessage());
 293  0
                 createNewCluModel(callback, workCompleteCallback);
 294  0
                 KSBlockingProgressIndicator.removeTask(loadDataTask);
 295  0
             }
 296  
 
 297  
             @Override
 298  
             public void onSuccess(Data result) {
 299  0
                 cluModel.setRoot(result);
 300  
                 //getContainer().setTitle(getSectionTitle());
 301  0
                 setHeaderTitle();
 302  0
                 updateCourseActionItems();
 303  0
                 callback.onModelReady(cluModel);
 304  0
                 workCompleteCallback.exec(true);
 305  0
                 reqDataModel.retrieveStatementTypes(cluModel.<String>get("id"), new Callback<Boolean>() {
 306  
                     @Override
 307  
                     public void exec(Boolean result) {
 308  0
                         if (result) {
 309  0
                             KSBlockingProgressIndicator.removeTask(loadDataTask);
 310  
                         }
 311  0
                     }
 312  
                 });
 313  
 
 314  0
             }
 315  
 
 316  
         });
 317  0
     }
 318  
     
 319  
     @SuppressWarnings("unchecked")
 320  
     private void getCurrentVersion(final ModelRequestCallback callback, final Callback<Boolean> workCompleteCallback) {
 321  0
             rpcServiceAsync.getData(courseId, new KSAsyncCallback<Data>(){
 322  
 
 323  
             @Override
 324  
             public void handleFailure(Throwable caught) {
 325  0
                 Window.alert("Error loading Course: "+caught.getMessage());
 326  0
                 createNewCluModel(callback, workCompleteCallback);
 327  0
                 KSBlockingProgressIndicator.removeTask(loadDataTask);
 328  0
             }
 329  
 
 330  
             @Override
 331  
             public void onSuccess(Data result) {
 332  0
                 cluModel.setRoot(result);
 333  
                 //getContainer().setTitle(getSectionTitle());
 334  0
                 setHeaderTitle();
 335  0
                 updateCourseActionItems();
 336  0
                 callback.onModelReady(cluModel);
 337  0
                 workCompleteCallback.exec(true);
 338  0
                 KSBlockingProgressIndicator.removeTask(loadDataTask);
 339  0
             }
 340  
 
 341  
         });
 342  0
     }
 343  
     
 344  
     @SuppressWarnings("unchecked")
 345  
     private void createNewCluModel(final ModelRequestCallback callback, final Callback<Boolean> workCompleteCallback){
 346  0
         cluModel.setRoot(new Data());
 347  0
         callback.onModelReady(cluModel);
 348  0
         workCompleteCallback.exec(true);
 349  0
     }
 350  
 
 351  
     public String getCourseId() {
 352  0
         return courseId;
 353  
     }
 354  
     
 355  
     public String getVersionIndId() {
 356  0
         return (String)cluModel.get("versionInfo/versionIndId");
 357  
     }
 358  
 
 359  
     public void setCourseId(String courseId) {
 360  0
         this.courseId = courseId;
 361  0
         this.cluModel.setRoot(new Data());        
 362  0
     }
 363  
        
 364  
     public void clear(String cluType){
 365  0
         super.clear();
 366  0
         this.cluType = cluType;
 367  0
         if (cluModel != null){
 368  0
             this.cluModel.setRoot(new Data());            
 369  
         }
 370  0
         this.courseId = null;
 371  0
     }    
 372  
     
 373  
     @Override
 374  
     public void showDefaultView(final Callback<Boolean> onReadyCallback) {
 375  0
         init(new Callback<Boolean>() {
 376  
 
 377  
             @Override
 378  
             public void exec(Boolean result) {
 379  0
                 if (result) {
 380  0
                         ViewCourseController.super.showDefaultView(onReadyCallback);
 381  
                 } else {
 382  0
                     onReadyCallback.exec(false);
 383  
                 }
 384  0
             }
 385  
         });
 386  0
     }
 387  
     
 388  
     @Override
 389  
     public void beforeShow(Callback<Boolean> onReadyCallback) {
 390  0
             showDefaultView(onReadyCallback);
 391  0
     }
 392  
     
 393  
     private KSButton getQuitButton(){
 394  0
         return new KSButton("Quit", new ClickHandler(){
 395  
                     public void onClick(ClickEvent event) {
 396  0
                             Application.navigate("/HOME/CURRICULUM_HOME");
 397  0
                     }
 398  
                 });       
 399  
     }
 400  
     
 401  
     
 402  
     protected void setHeaderTitle() {
 403  
                
 404  
             String title; 
 405  0
             if (cluModel.get("transcriptTitle") != null){
 406  0
                     title = getCourseTitle();
 407  
             }
 408  
             else{
 409  0
                     title = "Course";
 410  
             }
 411  
             
 412  0
             updateStatus();
 413  
             
 414  0
             this.setContentTitle(title);
 415  0
             this.setName(title);
 416  0
             WindowTitleUtils.setContextTitle(title);
 417  0
     }
 418  
     
 419  
     private void updateStatus() {
 420  0
             if(cluModel.get("state") != null){
 421  0
                     statusLabel.setText("Status: " + cluModel.get("state"));
 422  
             }
 423  0
     }
 424  
     
 425  
     private CloseHandler<KSLightBox> createActionSubmitSuccessHandler() {
 426  0
             CloseHandler<KSLightBox> handler = new CloseHandler<KSLightBox>(){
 427  
                         @Override
 428  
                         public void onClose(CloseEvent<KSLightBox> event) {
 429  
                                 //Reload the lum main entrypoint
 430  0
                                 Window.Location.reload();
 431  0
                         }
 432  
             };
 433  0
                 return handler;
 434  
         }
 435  
 
 436  
     public String getMessage(String courseMessageKey) {
 437  0
             String msg = Application.getApplicationContext().getMessage(MSG_GROUP, courseMessageKey);
 438  0
             if (msg == null) {
 439  0
                     msg = courseMessageKey;
 440  
             }
 441  0
             return msg;
 442  
     }
 443  
     
 444  
         public Widget getStatusLabel() {
 445  0
                 statusLabel.setStyleName("courseStatusLabel");
 446  0
                 return statusLabel;
 447  
         }
 448  
         
 449  
         public Widget getVersionHistoryWidget(){
 450  0
                 KSButton button = new KSButton("Version History", ButtonStyle.DEFAULT_ANCHOR, new ClickHandler(){
 451  
 
 452  
                         @Override
 453  
                         public void onClick(ClickEvent event) {
 454  0
                                 parentController.showView(ViewCourseParentController.Views.VERSIONS);
 455  0
                         }
 456  
                 });
 457  0
                 button.addStyleName("versionHistoryLink");
 458  0
                 return button;
 459  
                 
 460  
         }
 461  
         
 462  
         @Override
 463  
         public void onHistoryEvent(String historyStack) {
 464  0
                 super.onHistoryEvent(historyStack);
 465  0
                 if (cluModel.get("courseTitle") != null){
 466  0
                         RecentlyViewedHelper.addCurrentDocument(getCourseTitle());
 467  
                 }
 468  0
         }
 469  
         
 470  
         public String getCourseTitle(){
 471  0
                 return cluModel.get("courseTitle");
 472  
         }
 473  
 
 474  
         // this is misleading given the current version concept.  This just gets the id of the course
 475  
         public String getCurrentId() {
 476  0
                 return cluModel.get("id");
 477  
         }
 478  
 
 479  
     @Override
 480  
     public CourseRequirementsDataModel getReqDataModel() {
 481  0
         return reqDataModel;
 482  
     }
 483  
     
 484  
     @Override
 485  
     public DataModel getExportDataModel() {
 486  0
         return cluModel;
 487  
     }
 488  
     
 489  
     @Override
 490  
     public boolean isExportButtonActive() {
 491  0
         if (this.getCurrentViewEnum() != null && this.getCurrentViewEnum().equals(ViewCourseSections.DETAILED)) {
 492  0
             return true;
 493  
         }
 494  0
         return false;
 495  
     }
 496  
     
 497  
     @Override
 498  
     public ArrayList<ExportElement> getExportElementsFromView() {
 499  0
         ArrayList<ExportElement> exportElements = new ArrayList<ExportElement>();
 500  0
         if (this.getCurrentViewEnum().equals(ViewCourseSections.DETAILED)) {      
 501  0
             SummaryTableSection tableSection = this.cfg.getSummaryConfigurer().getTableSection();
 502  0
             ExportElement heading = new ExportElement();
 503  0
             heading.setFieldLabel("");
 504  0
             heading.setFieldValue(tableSection.getTitle());
 505  0
             exportElements.add(heading);
 506  0
             exportElements = ExportUtils.getDetailsForWidget(tableSection, exportElements);
 507  
         }
 508  0
         return exportElements;
 509  
     }
 510  
 }