// Path: elastic-config-console/src/main/java/com/github/config/observer/IObserver.java
// public interface IObserver {
// 
//     /**
//      * 通知
//      * 
//      * @param data
//      */
//     void notified(String data, String value);
// 
// }
// 
// Path: elastic-config-console/src/main/java/com/github/config/service/INodeService.java
// public interface INodeService {
// 
//     List<PropertyItem> findProperties(String node);
// 
//     List<String> listChildren(String node);
// 
//     boolean createProperty(String nodeName, String value);
// 
//     boolean updateProperty(String nodeName, String value);
// 
//     void deleteProperty(String nodeName);
// }
// 
// Path: elastic-config-console/src/main/java/com/github/config/service/entity/PropertyItem.java
// public class PropertyItem implements Serializable {
// 
//     private static final long serialVersionUID = -3189608011329109220L;
// 
//     private String name;
// 
//     private String value;
// 
//     public PropertyItem(String name, String value) {
//         super();
//         this.name = name;
//         this.value = value;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public void setName(String name) {
//         this.name = name;
//     }
// 
//     public String getValue() {
//         return value;
//     }
// 
//     public void setValue(String value) {
//         this.value = value;
//     }
// 
// }


import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import org.apache.curator.utils.ZKPaths;
import org.primefaces.component.inputtext.InputText;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.config.observer.IObserver;
import com.github.config.service.INodeService;
import com.github.config.service.entity.PropertyItem;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
    /**
     * 克隆版本
     */
    public void cloneVersion() {
        String versionToClone = (String) versionToCloneInput.getValue();
        if (!Strings.isNullOrEmpty(versionToClone) && !Strings.isNullOrEmpty(selectedVersion)) {

            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("Clone version [{}] from version [{}].", versionToClone, selectedVersion);
            }
            cloneTree(ZKPaths.makePath(nodeAuth.getAuthedNode(), selectedVersion),
                ZKPaths.makePath(nodeAuth.getAuthedNode(), versionToClone));
            cloneTree(ZKPaths.makePath(nodeAuth.getAuthedNode(), selectedVersion + "$"),
                ZKPaths.makePath(nodeAuth.getAuthedNode(), versionToClone + "$"));

            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Version cloned.", versionToClone));
            refresh();
            selectedVersion = versionToClone;
            versionToCloneInput.setValue("");
        }
    }

    private void cloneTree(String sourceVersionPath, String destinationVersionPath) {
        List<String> sourceGroups = nodeService.listChildren(sourceVersionPath);
        if (sourceGroups != null) {
            for (String sourceGroup : sourceGroups) {
                String sourceGroupFullPath = ZKPaths.makePath(sourceVersionPath, sourceGroup);
                String destinationGroupFullPath = ZKPaths.makePath(destinationVersionPath, sourceGroup);

                nodeService.createProperty(destinationGroupFullPath, null);
// Path: elastic-config-console/src/main/java/com/github/config/observer/IObserver.java
// public interface IObserver {
// 
//     /**
//      * 通知
//      * 
//      * @param data
//      */
//     void notified(String data, String value);
// 
// }
// 
// Path: elastic-config-console/src/main/java/com/github/config/service/INodeService.java
// public interface INodeService {
// 
//     List<PropertyItem> findProperties(String node);
// 
//     List<String> listChildren(String node);
// 
//     boolean createProperty(String nodeName, String value);
// 
//     boolean updateProperty(String nodeName, String value);
// 
//     void deleteProperty(String nodeName);
// }
// 
// Path: elastic-config-console/src/main/java/com/github/config/service/entity/PropertyItem.java
// public class PropertyItem implements Serializable {
// 
//     private static final long serialVersionUID = -3189608011329109220L;
// 
//     private String name;
// 
//     private String value;
// 
//     public PropertyItem(String name, String value) {
//         super();
//         this.name = name;
//         this.value = value;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public void setName(String name) {
//         this.name = name;
//     }
// 
//     public String getValue() {
//         return value;
//     }
// 
//     public void setValue(String value) {
//         this.value = value;
//     }
// 
// }


// Path: elastic-config-console/src/main/java/com/github/config/service/web/mb/VersionManagedBean.java
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import org.apache.curator.utils.ZKPaths;
import org.primefaces.component.inputtext.InputText;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.config.observer.IObserver;
import com.github.config.service.INodeService;
import com.github.config.service.entity.PropertyItem;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

    /**
     * 克隆版本
     */
    public void cloneVersion() {
        String versionToClone = (String) versionToCloneInput.getValue();
        if (!Strings.isNullOrEmpty(versionToClone) && !Strings.isNullOrEmpty(selectedVersion)) {

            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("Clone version [{}] from version [{}].", versionToClone, selectedVersion);
            }
            cloneTree(ZKPaths.makePath(nodeAuth.getAuthedNode(), selectedVersion),
                ZKPaths.makePath(nodeAuth.getAuthedNode(), versionToClone));
            cloneTree(ZKPaths.makePath(nodeAuth.getAuthedNode(), selectedVersion + "$"),
                ZKPaths.makePath(nodeAuth.getAuthedNode(), versionToClone + "$"));

            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Version cloned.", versionToClone));
            refresh();
            selectedVersion = versionToClone;
            versionToCloneInput.setValue("");
        }
    }

    private void cloneTree(String sourceVersionPath, String destinationVersionPath) {
        List<String> sourceGroups = nodeService.listChildren(sourceVersionPath);
        if (sourceGroups != null) {
            for (String sourceGroup : sourceGroups) {
                String sourceGroupFullPath = ZKPaths.makePath(sourceVersionPath, sourceGroup);
                String destinationGroupFullPath = ZKPaths.makePath(destinationVersionPath, sourceGroup);

                nodeService.createProperty(destinationGroupFullPath, null);
                List<PropertyItem> sourceProperties = nodeService.findProperties(sourceGroupFullPath);