001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.wiki.service.impl;
016    
017    import com.liferay.portal.kernel.configuration.Filter;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.search.Indexer;
023    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
024    import com.liferay.portal.kernel.systemevent.SystemEvent;
025    import com.liferay.portal.kernel.util.InstancePool;
026    import com.liferay.portal.kernel.util.PropsKeys;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.StringUtil;
029    import com.liferay.portal.kernel.util.UnicodeProperties;
030    import com.liferay.portal.kernel.util.Validator;
031    import com.liferay.portal.kernel.workflow.WorkflowConstants;
032    import com.liferay.portal.model.Group;
033    import com.liferay.portal.model.ResourceConstants;
034    import com.liferay.portal.model.SystemEventConstants;
035    import com.liferay.portal.model.User;
036    import com.liferay.portal.portletfilerepository.PortletFileRepositoryUtil;
037    import com.liferay.portal.service.ServiceContext;
038    import com.liferay.portal.util.PortletKeys;
039    import com.liferay.portal.util.PropsUtil;
040    import com.liferay.portal.util.PropsValues;
041    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
042    import com.liferay.portlet.trash.model.TrashEntry;
043    import com.liferay.portlet.trash.model.TrashVersion;
044    import com.liferay.portlet.trash.util.TrashUtil;
045    import com.liferay.portlet.wiki.DuplicateNodeNameException;
046    import com.liferay.portlet.wiki.NodeNameException;
047    import com.liferay.portlet.wiki.importers.WikiImporter;
048    import com.liferay.portlet.wiki.model.WikiNode;
049    import com.liferay.portlet.wiki.model.WikiPage;
050    import com.liferay.portlet.wiki.service.base.WikiNodeLocalServiceBaseImpl;
051    import com.liferay.portlet.wiki.util.WikiCacheThreadLocal;
052    import com.liferay.portlet.wiki.util.WikiCacheUtil;
053    
054    import java.io.InputStream;
055    
056    import java.util.ArrayList;
057    import java.util.Date;
058    import java.util.HashMap;
059    import java.util.List;
060    import java.util.Map;
061    
062    /**
063     * Provides the local service for accessing, adding, deleting, importing,
064     * subscription handling of, trash handling of, and updating wiki nodes.
065     *
066     * @author Brian Wing Shun Chan
067     * @author Charles May
068     * @author Raymond Aug??
069     */
070    public class WikiNodeLocalServiceImpl extends WikiNodeLocalServiceBaseImpl {
071    
072            @Override
073            public WikiNode addDefaultNode(long userId, ServiceContext serviceContext)
074                    throws PortalException, SystemException {
075    
076                    return addNode(
077                            userId, PropsValues.WIKI_INITIAL_NODE_NAME, StringPool.BLANK,
078                            serviceContext);
079            }
080    
081            @Override
082            public WikiNode addNode(
083                            long userId, String name, String description,
084                            ServiceContext serviceContext)
085                    throws PortalException, SystemException {
086    
087                    // Node
088    
089                    User user = userPersistence.findByPrimaryKey(userId);
090                    long groupId = serviceContext.getScopeGroupId();
091                    Date now = new Date();
092    
093                    validate(groupId, name);
094    
095                    long nodeId = counterLocalService.increment();
096    
097                    WikiNode node = wikiNodePersistence.create(nodeId);
098    
099                    node.setUuid(serviceContext.getUuid());
100                    node.setGroupId(groupId);
101                    node.setCompanyId(user.getCompanyId());
102                    node.setUserId(user.getUserId());
103                    node.setUserName(user.getFullName());
104                    node.setCreateDate(serviceContext.getCreateDate(now));
105                    node.setModifiedDate(serviceContext.getModifiedDate(now));
106                    node.setName(name);
107                    node.setDescription(description);
108    
109                    try {
110                            wikiNodePersistence.update(node);
111                    }
112                    catch (SystemException se) {
113                            if (_log.isWarnEnabled()) {
114                                    _log.warn(
115                                            "Add failed, fetch {groupId=" + groupId + ", name=" +
116                                                    name + "}");
117                            }
118    
119                            node = wikiNodePersistence.fetchByG_N(groupId, name, false);
120    
121                            if (node == null) {
122                                    throw se;
123                            }
124    
125                            return node;
126                    }
127    
128                    // Resources
129    
130                    if (serviceContext.isAddGroupPermissions() ||
131                            serviceContext.isAddGuestPermissions()) {
132    
133                            addNodeResources(
134                                    node, serviceContext.isAddGroupPermissions(),
135                                    serviceContext.isAddGuestPermissions());
136                    }
137                    else {
138                            addNodeResources(
139                                    node, serviceContext.getGroupPermissions(),
140                                    serviceContext.getGuestPermissions());
141                    }
142    
143                    return node;
144            }
145    
146            @Override
147            public void addNodeResources(
148                            long nodeId, boolean addGroupPermissions,
149                            boolean addGuestPermissions)
150                    throws PortalException, SystemException {
151    
152                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
153    
154                    addNodeResources(node, addGroupPermissions, addGuestPermissions);
155            }
156    
157            @Override
158            public void addNodeResources(
159                            long nodeId, String[] groupPermissions, String[] guestPermissions)
160                    throws PortalException, SystemException {
161    
162                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
163    
164                    addNodeResources(node, groupPermissions, guestPermissions);
165            }
166    
167            @Override
168            public void addNodeResources(
169                            WikiNode node, boolean addGroupPermissions,
170                            boolean addGuestPermissions)
171                    throws PortalException, SystemException {
172    
173                    resourceLocalService.addResources(
174                            node.getCompanyId(), node.getGroupId(), node.getUserId(),
175                            WikiNode.class.getName(), node.getNodeId(), false,
176                            addGroupPermissions, addGuestPermissions);
177            }
178    
179            @Override
180            public void addNodeResources(
181                            WikiNode node, String[] groupPermissions, String[] guestPermissions)
182                    throws PortalException, SystemException {
183    
184                    resourceLocalService.addModelResources(
185                            node.getCompanyId(), node.getGroupId(), node.getUserId(),
186                            WikiNode.class.getName(), node.getNodeId(), groupPermissions,
187                            guestPermissions);
188            }
189    
190            @Override
191            public void deleteNode(long nodeId)
192                    throws PortalException, SystemException {
193    
194                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
195    
196                    wikiNodeLocalService.deleteNode(node);
197            }
198    
199            @Override
200            @SystemEvent(
201                    action = SystemEventConstants.ACTION_SKIP,
202                    type = SystemEventConstants.TYPE_DELETE)
203            public void deleteNode(WikiNode node)
204                    throws PortalException, SystemException {
205    
206                    // Pages
207    
208                    wikiPageLocalService.deletePages(node.getNodeId());
209    
210                    // Node
211    
212                    wikiNodePersistence.remove(node);
213    
214                    // Resources
215    
216                    resourceLocalService.deleteResource(
217                            node.getCompanyId(), WikiNode.class.getName(),
218                            ResourceConstants.SCOPE_INDIVIDUAL, node.getNodeId());
219    
220                    // Attachments
221    
222                    long folderId = node.getAttachmentsFolderId();
223    
224                    if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
225                            PortletFileRepositoryUtil.deleteFolder(folderId);
226                    }
227    
228                    // Subscriptions
229    
230                    subscriptionLocalService.deleteSubscriptions(
231                            node.getCompanyId(), WikiNode.class.getName(), node.getNodeId());
232    
233                    if (node.isInTrash()) {
234                            node.setName(TrashUtil.getOriginalTitle(node.getName()));
235    
236                            // Trash
237    
238                            trashEntryLocalService.deleteEntry(
239                                    WikiNode.class.getName(), node.getNodeId());
240    
241                            // Indexer
242    
243                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
244                                    WikiNode.class);
245    
246                            indexer.delete(node);
247                    }
248            }
249    
250            @Override
251            public void deleteNodes(long groupId)
252                    throws PortalException, SystemException {
253    
254                    List<WikiNode> nodes = wikiNodePersistence.findByGroupId(groupId);
255    
256                    for (WikiNode node : nodes) {
257                            wikiNodeLocalService.deleteNode(node);
258                    }
259    
260                    PortletFileRepositoryUtil.deletePortletRepository(
261                            groupId, PortletKeys.WIKI);
262            }
263    
264            @Override
265            public WikiNode fetchNode(long groupId, String name)
266                    throws SystemException {
267    
268                    return wikiNodePersistence.fetchByG_N(groupId, name);
269            }
270    
271            @Override
272            public WikiNode fetchNodeByUuidAndGroupId(String uuid, long groupId)
273                    throws SystemException {
274    
275                    return wikiNodePersistence.fetchByUUID_G(uuid, groupId);
276            }
277    
278            @Override
279            public List<WikiNode> getCompanyNodes(long companyId, int start, int end)
280                    throws SystemException {
281    
282                    return wikiNodePersistence.findByC_S(
283                            companyId, WorkflowConstants.STATUS_APPROVED, start, end);
284            }
285    
286            @Override
287            public List<WikiNode> getCompanyNodes(
288                            long companyId, int status, int start, int end)
289                    throws SystemException {
290    
291                    return wikiNodePersistence.findByC_S(companyId, status, start, end);
292            }
293    
294            @Override
295            public int getCompanyNodesCount(long companyId) throws SystemException {
296                    return wikiNodePersistence.countByC_S(
297                            companyId, WorkflowConstants.STATUS_APPROVED);
298            }
299    
300            @Override
301            public int getCompanyNodesCount(long companyId, int status)
302                    throws SystemException {
303    
304                    return wikiNodePersistence.countByC_S(companyId, status);
305            }
306    
307            @Override
308            public WikiNode getNode(long nodeId)
309                    throws PortalException, SystemException {
310    
311                    return wikiNodePersistence.findByPrimaryKey(nodeId);
312            }
313    
314            @Override
315            public WikiNode getNode(long groupId, String nodeName)
316                    throws PortalException, SystemException {
317    
318                    return wikiNodePersistence.findByG_N(groupId, nodeName);
319            }
320    
321            @Override
322            public List<WikiNode> getNodes(long groupId)
323                    throws PortalException, SystemException {
324    
325                    return getNodes(groupId, WorkflowConstants.STATUS_APPROVED);
326            }
327    
328            @Override
329            public List<WikiNode> getNodes(long groupId, int status)
330                    throws PortalException, SystemException {
331    
332                    List<WikiNode> nodes = wikiNodePersistence.findByG_S(groupId, status);
333    
334                    if (nodes.isEmpty()) {
335                            nodes = addDefaultNode(groupId);
336                    }
337    
338                    return nodes;
339            }
340    
341            @Override
342            public List<WikiNode> getNodes(long groupId, int start, int end)
343                    throws PortalException, SystemException {
344    
345                    return getNodes(groupId, WorkflowConstants.STATUS_APPROVED, start, end);
346            }
347    
348            @Override
349            public List<WikiNode> getNodes(long groupId, int status, int start, int end)
350                    throws PortalException, SystemException {
351    
352                    List<WikiNode> nodes = wikiNodePersistence.findByG_S(
353                            groupId, status, start, end);
354    
355                    if (nodes.isEmpty()) {
356                            nodes = addDefaultNode(groupId);
357                    }
358    
359                    return nodes;
360            }
361    
362            @Override
363            public int getNodesCount(long groupId) throws SystemException {
364                    return wikiNodePersistence.countByG_S(
365                            groupId, WorkflowConstants.STATUS_APPROVED);
366            }
367    
368            @Override
369            public int getNodesCount(long groupId, int status) throws SystemException {
370                    return wikiNodePersistence.countByG_S(groupId, status);
371            }
372    
373            @Override
374            public void importPages(
375                            long userId, long nodeId, String importer,
376                            InputStream[] inputStreams, Map<String, String[]> options)
377                    throws PortalException, SystemException {
378    
379                    WikiNode node = getNode(nodeId);
380    
381                    WikiImporter wikiImporter = getWikiImporter(importer);
382    
383                    wikiImporter.importPages(userId, node, inputStreams, options);
384            }
385    
386            @Override
387            public WikiNode moveNodeToTrash(long userId, long nodeId)
388                    throws PortalException, SystemException {
389    
390                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
391    
392                    return moveNodeToTrash(userId, node);
393            }
394    
395            @Override
396            public WikiNode moveNodeToTrash(long userId, WikiNode node)
397                    throws PortalException, SystemException {
398    
399                    // Node
400    
401                    int oldStatus = node.getStatus();
402    
403                    node = updateStatus(
404                            userId, node, WorkflowConstants.STATUS_IN_TRASH,
405                            new ServiceContext());
406    
407                    // Trash
408    
409                    UnicodeProperties typeSettingsProperties = new UnicodeProperties();
410    
411                    typeSettingsProperties.put("title", node.getName());
412    
413                    TrashEntry trashEntry = trashEntryLocalService.addTrashEntry(
414                            userId, node.getGroupId(), WikiNode.class.getName(),
415                            node.getNodeId(), node.getUuid(), null, oldStatus, null,
416                            typeSettingsProperties);
417    
418                    node.setName(TrashUtil.getTrashTitle(trashEntry.getEntryId()));
419    
420                    wikiNodePersistence.update(node);
421    
422                    // Pages
423    
424                    moveDependentsToTrash(node.getNodeId(), trashEntry.getEntryId());
425    
426                    return node;
427            }
428    
429            @Override
430            public void restoreNodeFromTrash(long userId, WikiNode node)
431                    throws PortalException, SystemException {
432    
433                    // Node
434    
435                    node.setName(TrashUtil.getOriginalTitle(node.getName()));
436    
437                    wikiNodePersistence.update(node);
438    
439                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
440                            WikiNode.class.getName(), node.getNodeId());
441    
442                    updateStatus(
443                            userId, node, trashEntry.getStatus(), new ServiceContext());
444    
445                    // Pages
446    
447                    restoreDependentFromTrash(node.getNodeId(), trashEntry.getEntryId());
448    
449                    // Trash
450    
451                    trashEntryLocalService.deleteEntry(trashEntry);
452            }
453    
454            @Override
455            public void subscribeNode(long userId, long nodeId)
456                    throws PortalException, SystemException {
457    
458                    WikiNode node = getNode(nodeId);
459    
460                    subscriptionLocalService.addSubscription(
461                            userId, node.getGroupId(), WikiNode.class.getName(), nodeId);
462            }
463    
464            @Override
465            public void unsubscribeNode(long userId, long nodeId)
466                    throws PortalException, SystemException {
467    
468                    subscriptionLocalService.deleteSubscription(
469                            userId, WikiNode.class.getName(), nodeId);
470            }
471    
472            @Override
473            public WikiNode updateNode(
474                            long nodeId, String name, String description,
475                            ServiceContext serviceContext)
476                    throws PortalException, SystemException {
477    
478                    WikiNode node = wikiNodePersistence.findByPrimaryKey(nodeId);
479    
480                    validate(nodeId, node.getGroupId(), name);
481    
482                    node.setModifiedDate(serviceContext.getModifiedDate(null));
483                    node.setName(name);
484                    node.setDescription(description);
485    
486                    wikiNodePersistence.update(node);
487    
488                    return node;
489            }
490    
491            @Override
492            public WikiNode updateStatus(
493                            long userId, WikiNode node, int status,
494                            ServiceContext serviceContext)
495                    throws PortalException, SystemException {
496    
497                    // Node
498    
499                    User user = userPersistence.findByPrimaryKey(userId);
500    
501                    Date now = new Date();
502    
503                    node.setStatus(status);
504                    node.setStatusByUserId(userId);
505                    node.setStatusByUserName(user.getFullName());
506                    node.setStatusDate(now);
507    
508                    wikiNodePersistence.update(node);
509    
510                    // Indexer
511    
512                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
513                            WikiNode.class);
514    
515                    indexer.reindex(node);
516    
517                    return node;
518            }
519    
520            protected List<WikiNode> addDefaultNode(long groupId)
521                    throws PortalException, SystemException {
522    
523                    Group group = groupPersistence.findByPrimaryKey(groupId);
524    
525                    long defaultUserId = userLocalService.getDefaultUserId(
526                            group.getCompanyId());
527    
528                    ServiceContext serviceContext = new ServiceContext();
529    
530                    serviceContext.setAddGroupPermissions(true);
531                    serviceContext.setAddGuestPermissions(true);
532                    serviceContext.setScopeGroupId(groupId);
533    
534                    WikiNode node = wikiNodeLocalService.addDefaultNode(
535                            defaultUserId, serviceContext);
536    
537                    List<WikiNode> nodes = new ArrayList<WikiNode>(1);
538    
539                    nodes.add(node);
540    
541                    return nodes;
542            }
543    
544            protected WikiImporter getWikiImporter(String importer)
545                    throws SystemException {
546    
547                    WikiImporter wikiImporter = _wikiImporters.get(importer);
548    
549                    if (wikiImporter == null) {
550                            String importerClass = PropsUtil.get(
551                                    PropsKeys.WIKI_IMPORTERS_CLASS, new Filter(importer));
552    
553                            if (importerClass != null) {
554                                    wikiImporter = (WikiImporter)InstancePool.get(importerClass);
555    
556                                    _wikiImporters.put(importer, wikiImporter);
557                            }
558    
559                            if (importer == null) {
560                                    throw new SystemException(
561                                            "Unable to instantiate wiki importer class " +
562                                                    importerClass);
563                            }
564                    }
565    
566                    return wikiImporter;
567            }
568    
569            protected void moveDependentsToTrash(long nodeId, long trashEntryId)
570                    throws PortalException, SystemException {
571    
572                    List<WikiPage> pages = wikiPagePersistence.findByNodeId(nodeId);
573    
574                    for (WikiPage page : pages) {
575    
576                            // Page
577    
578                            int oldStatus = page.getStatus();
579    
580                            if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
581                                    continue;
582                            }
583    
584                            // Version pages
585    
586                            List<WikiPage> versionPages = wikiPagePersistence.findByR_N(
587                                    page.getResourcePrimKey(), page.getNodeId());
588    
589                            for (WikiPage versionPage : versionPages) {
590    
591                                    // Version page
592    
593                                    int versionPageOldStatus = versionPage.getStatus();
594    
595                                    versionPage.setStatus(WorkflowConstants.STATUS_IN_TRASH);
596    
597                                    wikiPagePersistence.update(versionPage);
598    
599                                    // Trash
600    
601                                    int status = versionPageOldStatus;
602    
603                                    if (versionPageOldStatus ==
604                                                    WorkflowConstants.STATUS_PENDING) {
605    
606                                            status = WorkflowConstants.STATUS_DRAFT;
607                                    }
608    
609                                    if (versionPageOldStatus !=
610                                                    WorkflowConstants.STATUS_APPROVED) {
611    
612                                            trashVersionLocalService.addTrashVersion(
613                                                    trashEntryId, WikiPage.class.getName(),
614                                                    versionPage.getPageId(), status, null);
615                                    }
616                            }
617    
618                            // Asset
619    
620                            if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
621                                    assetEntryLocalService.updateVisible(
622                                            WikiPage.class.getName(), page.getResourcePrimKey(), false);
623                            }
624    
625                            // Index
626    
627                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
628                                    WikiPage.class);
629    
630                            indexer.reindex(page);
631    
632                            // Cache
633    
634                            if (WikiCacheThreadLocal.isClearCache()) {
635                                    WikiCacheUtil.clearCache(page.getNodeId());
636                            }
637    
638                            // Workflow
639    
640                            if (oldStatus == WorkflowConstants.STATUS_PENDING) {
641                                    workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
642                                            page.getCompanyId(), page.getGroupId(),
643                                            WikiPage.class.getName(), page.getResourcePrimKey());
644                            }
645                    }
646            }
647    
648            protected void restoreDependentFromTrash(long nodeId, long trashEntryId)
649                    throws PortalException, SystemException {
650    
651                    List<WikiPage> pages = wikiPagePersistence.findByN_H(nodeId, true);
652    
653                    for (WikiPage page : pages) {
654    
655                            // Page
656    
657                            TrashEntry trashEntry = trashEntryLocalService.fetchEntry(
658                                    WikiPage.class.getName(), page.getResourcePrimKey());
659    
660                            if (trashEntry != null) {
661                                    continue;
662                            }
663    
664                            TrashVersion trashVersion = trashVersionLocalService.fetchVersion(
665                                    trashEntryId, WikiPage.class.getName(), page.getPageId());
666    
667                            int oldStatus = WorkflowConstants.STATUS_APPROVED;
668    
669                            if (trashVersion != null) {
670                                    oldStatus = trashVersion.getStatus();
671                            }
672    
673                            // Version pages
674    
675                            List<WikiPage> versionPages = wikiPagePersistence.findByR_N(
676                                    page.getResourcePrimKey(), page.getNodeId());
677    
678                            for (WikiPage versionPage : versionPages) {
679    
680                                    // Version page
681    
682                                    trashVersion = trashVersionLocalService.fetchVersion(
683                                            trashEntryId, WikiPage.class.getName(),
684                                            versionPage.getPageId());
685    
686                                    int versionPageOldStatus = WorkflowConstants.STATUS_APPROVED;
687    
688                                    if (trashVersion != null) {
689                                            versionPageOldStatus = trashVersion.getStatus();
690                                    }
691    
692                                    versionPage.setStatus(versionPageOldStatus);
693    
694                                    wikiPagePersistence.update(versionPage);
695    
696                                    // Trash
697    
698                                    if (trashVersion != null) {
699                                            trashVersionLocalService.deleteTrashVersion(trashVersion);
700                                    }
701                            }
702    
703                            // Asset
704    
705                            if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
706                                    assetEntryLocalService.updateVisible(
707                                            WikiPage.class.getName(), page.getResourcePrimKey(), true);
708                            }
709    
710                            // Index
711    
712                            Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
713                                    WikiPage.class);
714    
715                            indexer.reindex(page);
716                    }
717            }
718    
719            protected void validate(long nodeId, long groupId, String name)
720                    throws PortalException, SystemException {
721    
722                    if (StringUtil.equalsIgnoreCase(name, "tag")) {
723                            throw new NodeNameException(name + " is reserved");
724                    }
725    
726                    if (Validator.isNull(name)) {
727                            throw new NodeNameException();
728                    }
729    
730                    WikiNode node = wikiNodePersistence.fetchByG_N(groupId, name);
731    
732                    if ((node != null) && (node.getNodeId() != nodeId)) {
733                            throw new DuplicateNodeNameException("{nodeId=" + nodeId + "}");
734                    }
735            }
736    
737            protected void validate(long groupId, String name)
738                    throws PortalException, SystemException {
739    
740                    validate(0, groupId, name);
741            }
742    
743            private static Log _log = LogFactoryUtil.getLog(
744                    WikiNodeLocalServiceImpl.class);
745    
746            private Map<String, WikiImporter> _wikiImporters =
747                    new HashMap<String, WikiImporter>();
748    
749    }