void changePrimaryType()

in eclipse/eclipse-ui/src/org/apache/sling/ide/eclipse/ui/nav/model/JcrNode.java [1139:1323]


    void changePrimaryType(String newPrimaryType) {
        Repository repository = ServerUtil.getDefaultRepository(getProject());
        NodeTypeRegistry ntManager = (repository==null) ? null : repository.getNodeTypeRegistry();
        if (ntManager == null) {
            MessageDialog.openWarning(null, "Unable to change primary type", "Unable to change primary type since project "
                    + getProject().getName() + " is not associated with a server or the server is not started.");
            return;
        }
        
        try {
            if (!ntManager.isAllowedPrimaryChildNodeType(getParent().getPrimaryType(), newPrimaryType)) {
                if (!MessageDialog.openQuestion(null, "Unable to change primary type", "Parent (type '"+getParent().getPrimaryType()+"')"+
                        " does not accept child with primary type '"+newPrimaryType+"'. Change anyway?")) {
                    return;
                }
            }
        } catch (RepositoryException e1) {
            MessageDialog.openWarning(null, "Unable to change primary type", "Exception occured while trying to "+
                    "verify node types: "+e1);
            return;
        }
        String thisNodeType = getPrimaryType();
        final SerializationKind currentSk = getSerializationKind(thisNodeType);
        final SerializationKind newSk = getSerializationKind(newPrimaryType);
        
        if (currentSk.equals(newSk)) {
            if (newSk!=SerializationKind.FOLDER) {
                // easiest - we should just be able to change the type in the .content.xml
                properties.doSetPropertyValue("jcr:primaryType", newPrimaryType);
            } else {
                if (thisNodeType.equals("nt:folder")) {
                    // switching away from an nt:folder might require creating a .content.xml
                    createVaultFile((IFolder) resource, ".content.xml", newPrimaryType);
                } else if (newPrimaryType.equals("nt:folder")) {
                    // switching *to* an nt:folder also has its challenges..:
                    // 1) it is not allowed to occur within a 'default' and 'full coverage aggregate' node
                    // 2) nt:folder doesn't allow arbitrary children for one
                    // 3)  but it also doesn't have an extra .content.xml - so that one would disappear
                    
                    // 1)
                    if (domElement!=null) {
                        MessageDialog.openWarning(null, "Unable to change primaryType", "Unable to change jcr:primaryType to nt:folder"
                                + " since the node is contained in a .content.xml");
                        return;
                    }
                    
                    
                    // verify 2)
                    if (!verifyNodeTypeChange(ntManager, newPrimaryType)) {
                        return;
                    }
                    if (!(resource instanceof IFolder)) {
                        MessageDialog.openWarning(null, "Unable to change primaryType", "Unable to change jcr:primaryType to nt:folder"
                                + " as there is no underlying folder");
                        return;
                    }
                    IFolder folder = (IFolder)resource;
                    // 3) delete the .content.xml
                    IFile contentXml = folder.getFile(".content.xml");
                    if (contentXml.exists()) {
                        try {
                            contentXml.delete(true, new NullProgressMonitor());
                        } catch (CoreException e) {
                            Logger logger = Activator.getDefault().getPluginLogger();
                            logger.error("Could not delete "+contentXml.getFullPath()+", e="+e, e);
                            MessageDialog.openError(null, "Could not delete file",
                                    "Could not delete "+contentXml.getFullPath()+", "+e);
                        }
                    }
                } else {
                    properties.doSetPropertyValue("jcr:primaryType", newPrimaryType);
                }
            }
            return;
        }
        
        if (newSk==SerializationKind.FOLDER) {
            // switching to a folder
            if (currentSk==SerializationKind.FILE) {
                MessageDialog.openWarning(null, "Unable to change primary type",
                        "Changing from a file to a folder type is currently not supported");
                return;
            }
            if (newPrimaryType.equals("nt:folder")) {
                // verify
                if (!verifyNodeTypeChange(ntManager, newPrimaryType)) {
                    return;
                }
            }
            try {
                // create the new directory structure pointing to 'this'
                IFolder newFolder = getParent().prepareCreateFolderChild(getJcrPathName());
                
                if (!newPrimaryType.equals("nt:folder")) {
                    // move any children from the existing 'this' to a new vault file
                    createVaultFileWithContent(newFolder, ".content.xml", newPrimaryType, domElement);
                }
                
                // remove myself
                if (domElement!=null) {
                    domElement.remove();
                    if (underlying!=null) {
                        underlying.save();
                    }
                }

                // add a pointer in the corresponding .content.xml to point to this (folder) child
                getParent().createDomChild(getJcrPathName(), 
                        null);
                if (newPrimaryType.equals("nt:folder")) {
                    // delete the .content.xml
                    if (properties!=null && properties.getUnderlying()!=null) {
                        IFile contentXml = properties.getUnderlying().file;
                        if (contentXml!=null && contentXml.exists()) {
                            contentXml.delete(true, new NullProgressMonitor());
                        }
                    }
                }
                ServerUtil.triggerIncrementalBuild(newFolder, null);
                return;
            } catch (CoreException e) {
                MessageDialog.openWarning(null, "Unable to change primaryType", "Exception occurred: "+e);
                Logger logger = Activator.getDefault().getPluginLogger();
                logger.error("Exception occurred", e);
                return;
            }
        } else if (newSk==SerializationKind.FILE) {
            MessageDialog.openWarning(null, "Unable to change primary type",
                    "Changing to/from a file is currently not supported");
            return;
        } else {
            // otherwise we're going from a folder to partial-or-full
            if (domElement==null && (resource instanceof IFolder)) {
                createVaultFile((IFolder) resource, ".content.xml", newPrimaryType);
            } else {
                
                // set the "pointer"'s jcr:primaryType
                if (domElement.getAttributeMap().containsKey("jcr:primaryType")) {
                    domElement.setAttribute("jcr:primaryType", newPrimaryType);
                } else {
                    domElement.addAttribute("jcr:primaryType", newPrimaryType);
                }
                
                // then copy all the other attributes - plus children if there are nay
                Element propDomElement = properties.getDomElement();
                if (propDomElement!=null) {
                    List<Attribute> attributes = propDomElement.getAttributes();
                    for (Iterator<Attribute> it = attributes.iterator(); it.hasNext();) {
                        Attribute anAttribute = it.next();
                        if (anAttribute.getName().startsWith("xmlns:")) {
                            continue;
                        }
                        if (anAttribute.getName().equals("jcr:primaryType")) {
                            continue;
                        }
                        if (domElement.getAttributeMap().containsKey(anAttribute.getName())) {
                            domElement.setAttribute(anAttribute.getName(), anAttribute.getValue());
                        } else {
                            domElement.addAttribute(anAttribute);
                        }
                    }
                    List<Element> c2 = propDomElement.getChildren();
                    if (c2!=null && c2.size()!=0) {
                        domElement.addNodes(c2);
                    }
                }
                
                if (properties.getUnderlying()!=null && properties.getUnderlying().file!=null) {
                    try {
                        properties.getUnderlying().file.delete(true, new NullProgressMonitor());
                        // prune empty directories:
                        prune(properties.getUnderlying().file.getParent());
                    } catch (CoreException e) {
                        MessageDialog.openError(null, "Unable to change primary type",
                                "Could not delete vault file "+properties.getUnderlying().file+": "+e);
                        Activator.getDefault().getPluginLogger().error("Error changing jcr:primaryType. Could not delete vault file "+properties.getUnderlying().file+": "+e.getMessage(), e);
                        return;
                    }
                }
                
                underlying.save();
            }
        }
        
    }