LocalHistoryRootNode.java :  » IDE-Netbeans » localhistory » org » netbeans » modules » localhistory » ui » view » Java Open Source

Java Open Source » IDE Netbeans » localhistory 
localhistory » org » netbeans » modules » localhistory » ui » view » LocalHistoryRootNode.java
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common
 * Development and Distribution License("CDDL") (collectively, the
 * "License"). You may not use this file except in compliance with the
 * License. You can obtain a copy of the License at
 * http://www.netbeans.org/cddl-gplv2.html
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 * specific language governing permissions and limitations under the
 * License.  When distributing the software, include this License Header
 * Notice in each file and include the License file at
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the GPL Version 2 section of the License file that
 * accompanied this code. If applicable, add the following below the
 * License Header, with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Contributor(s):
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 * Microsystems, Inc. All Rights Reserved.
 *
 * If you wish your version of this file to be governed by only the CDDL
 * or only the GPL Version 2, indicate your decision by adding
 * "[Contributor] elects to include this software in this distribution
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 * single choice of license, a recipient has the option to distribute
 * your version of this file under either the CDDL, the GPL Version 2 or
 * to extend the choice of license to its licensees as provided above.
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 * Version 2 license, then the option applies only if the new code is
 * made subject to such option by the copyright holder.
 */
package org.netbeans.modules.localhistory.ui.view;

import java.awt.Image;
import java.beans.BeanInfo;
import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import javax.swing.Action;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.UIManager;
import org.netbeans.modules.localhistory.LocalHistory;
import org.netbeans.modules.localhistory.store.StoreEntry;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;

/**
 *
 * The toplevel Node in the LocalHistoryView
 * 
 * <ul> 
 * <li>
 * In case the LocalHistoryView was invoked for a 1 file Node
 * 
 * LocalHistoryViewRootNode ( uvisible root node )
 *  |
 *  +-------- DateFolderNode ( Today ) 
 *              |
 *              +---------- StoreEntryNode ( 29.01.2007 02:15:07 PM ) 
 *              +---------- StoreEntryNode ( 29.01.2007 02:14:59 PM )
 *  
 *  +-------- DateFolderNode ( One day ago )
 *              |
 *              +---------- StoreEntryNode ( 28.01.2007 07:50:59 PM ) 
 *              +---------- StoreEntryNode ( 28.01.2007 03:11:50 PM ) 
 *              +---------- StoreEntryNode ( 28.01.2007 01:15:04 PM )
 *
 * </li>
 * 
 * <li>
 * In case the LocalHistoryView was invoked for a multifile Node
 * 
 * LocalHistoryViewRootNode ( uvisible root node )
 *  |
 *  +-------- DateFolderNode ( Today ) 
 *              |
 *              +---------- StoreEntryNode ( 29.01.2007 02:15:07 PM ) 
 *                              |
 *                              +--------- FileNode ( MyPanel.java )    
 *                              +--------- FileNode ( MyPanel.form )    
 * 
 *              +---------- StoreEntryNode ( 29.01.2007 01:11:23 PM ) 
 *                              |
 *                              +--------- FileNode ( MyPanel.java )    
 *                              +--------- FileNode ( MyPanel.form )     
 *  
 *  +-------- One day ago ( DateFolderNode )
 *  |
 *  +-------- Two days ago ( DateFolderNode )
 * 
 * </li>
 * </ul>
 * 
 * 
 * @author Tomas Stupka
 *
 */
public class LocalHistoryRootNode extends AbstractNode {
    
    static final Action[] NO_ACTION = new Action[0];
    
    private LocalHistoryRootNode(Children children) {
        super(children);
    }
    
    /**
     * 
     * Creates the LocalHistoryViewRootNode with the whole node hierarchy  
     * 
     * @param files files represented by the node on which the LocalHistoryView was invoked - e.g. Main.java, or MyForm.form, MyForm.java, ...
     * @return a node to be applyied as a roo tnode in the LocalHistoryView 
     */
    static Node createRootNode(File[] files) {        
        Children.SortedArray children = new Children.SortedArray();                
        children.add(createDateFolders(files));        
        return new LocalHistoryRootNode(children);        
    }
    
    /**
     * 
     * Creates the DateFolderNodes
     *
     * @param files files represented by the node on which the LocalHistoryView was invoked - e.g. Main.java, or MyForm.form, MyForm.java, ...
     * @return an array of nodes segmenting all entries for the invoked output in separate folders - one for each day
     */
    private static DateFolderNode[] createDateFolders(File[] files) {
        
        // get all StoreEntries for all files and keep them in entriesMap, where 
        // for each timestamp retrieved from the storage there is an array of StoreEntries
        Map<Long, List<StoreEntry>> entriesMap = new HashMap<Long, List<StoreEntry>>();                        
        for (File f : files) {
            StoreEntry[] ses = LocalHistory.getInstance().getLocalHistoryStore().getStoreEntries(f);
            for(StoreEntry se : ses) {
                List<StoreEntry> storeEntries = entriesMap.get(se.getTimestamp());
                if(storeEntries == null) {
                    storeEntries = new ArrayList<StoreEntry>();
                    entriesMap.put(se.getTimestamp(), storeEntries);
                }
                storeEntries.add(se);
            }
        }
                    
        Map<Integer, List<Node>> storeEntryNodesToDays = new HashMap<Integer, List<Node>>();        
        
        // segment the StoreEntries in day groups
        for (Long ts  : entriesMap.keySet()) {                      
            int day = getDay(ts);                                                        
            List<Node> nodesFromADay =  storeEntryNodesToDays.get(day);
            if(nodesFromADay == null) {
                nodesFromADay = new ArrayList<Node>();
                 storeEntryNodesToDays.put(day, nodesFromADay);
            }
            List<StoreEntry> storeEntries = entriesMap.get(ts);
            nodesFromADay.add(createStoreEntryNode(storeEntries, files));
        }

        // get a DateFolderNode for each day and the associated group of StoreEntryNode-s
        List<DateFolderNode> dateFolderNodes = new ArrayList<DateFolderNode>( storeEntryNodesToDays.keySet().size());
        for (Iterator<Integer> it =  storeEntryNodesToDays.keySet().iterator(); it.hasNext();) {
            int key = it.next();            
            List<Node> l =  storeEntryNodesToDays.get(key);
            Children.SortedArray children = new Children.SortedArray();            
            children.add(l.toArray(new Node[l.size()]));
            
            dateFolderNodes.add(new DateFolderNode(key, children));
        }

        return dateFolderNodes.toArray(new DateFolderNode[dateFolderNodes.size()]);
    }                
    
    private static int getDay(long ts) {
        Date date = new Date(ts);
                
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());        
        
        // set the cal at today midnight
        int todayMillis = c.get(Calendar.HOUR_OF_DAY) * 60 * 60 * 1000 +
                          c.get(Calendar.MINUTE)      * 60 * 1000 + 
                          c.get(Calendar.SECOND)      * 1000 + 
                          c.get(Calendar.MILLISECOND);                
        c.add(Calendar.MILLISECOND, -1 * todayMillis);                        
        
        if(c.getTime().compareTo(date) < 0) {
            return 0;
        }
        
        return (int) ( (c.getTimeInMillis() - ts) / (24 * 60 * 60 * 1000) ) + 1;
                
    }
    
    /**
     * 
     * Creates a StoreEntryNode for a list of files, where the files are related to one DataObject - e.g. MyForm.java, MyForm.form
     * 
     */
    private static Node createStoreEntryNode(List<StoreEntry> entries, File[] files) {
        if(files.length == 1) {
            
            // it's only 1 file, so we also already have the 1 StoreEntry
            return StoreEntryNode.create(entries);
            
        } else {            
            // it's a multifile node ...             
            
            // the timestamp must be the same for all StoreEntries
            long ts = entries.get(0).getTimestamp();           
            
            // get the entries for every file - 
            // if there is no entry in the Storage then create a structural (fake) one 
            List<StoreEntry> entriesList = new ArrayList<StoreEntry>();            
            for(File f : files) {                
                boolean fileInEntries = false;
                // check if we already have an entry for the file
                for(StoreEntry se : entries) {
                    if(f.equals(se.getFile())) {
                        entriesList.add(se);
                        fileInEntries = true;
                        break;
                    }
                }
                if(fileInEntries) {
                    // continue if we already have an entry for the file 
                    continue;
                }
                                
                // if there was no entry for the the file then try to get it ...
                StoreEntry e = LocalHistory.getInstance().getLocalHistoryStore().getStoreEntry(f, ts);
                if(e != null) {
                    
                    // XXX we probably don't have to do this anymore - see in createDateFolders( ... )
                    
                    // ... either by retrieving them from the storage
                    entriesList.add(e);
                } else {
                    // ... or by creating a structural (fake) one
                    entriesList.add(StoreEntry.createFakeStoreEntry(f, ts));
                }                
            }            
            return StoreEntryNode.create(entriesList);            
        }
    }                                     

    public String getName() {
        return "rootnode"; // NOI18N
    }
    
    public String getDisplayName() {
        return NbBundle.getMessage(LocalHistoryRootNode.class, "LBL_LocalHistory_Column_Version"); // NOI18N
    }            
        
    public Action[] getActions(boolean context) {
        return NO_ACTION;
    }
        
    static class DateFolderNode extends AbstractNode implements Comparable {
        private final int day;

        DateFolderNode(int day, Children children) {
            super(children);                        
            this.day = day;
        }

        int getDay() {
            return day;
        }

        public Image getIcon(int type) {
            Image img = null;
            if (type == BeanInfo.ICON_COLOR_16x16) {
                img = (Image) UIManager.get("Nb.Explorer.Folder.icon");  // NOI18N
            }
            if (img == null) {
                img = super.getIcon(type);
            }
            return img;
        }

        public Image getOpenedIcon(int type) {
            Image img = null;
            if (type == BeanInfo.ICON_COLOR_16x16) {
                img = (Image) UIManager.get("Nb.Explorer.Folder.openedIcon");  // NOI18N
            }
            if (img == null) {
                img = super.getIcon(type);
            }
            return img;
        }      

        public Action[] getActions(boolean context) {
            return NO_ACTION;
        }

        public String getName() {
            switch (day) {
                case 0: return NbBundle.getMessage(LocalHistoryRootNode.class, "DateFolderName_0");                
                case 1: return NbBundle.getMessage(LocalHistoryRootNode.class, "DateFolderName_1");                
                case 2: return NbBundle.getMessage(LocalHistoryRootNode.class, "DateFolderName_2");                
                case 3: return NbBundle.getMessage(LocalHistoryRootNode.class, "DateFolderName_3");                
                case 4: return NbBundle.getMessage(LocalHistoryRootNode.class, "DateFolderName_4");                
                case 5: return NbBundle.getMessage(LocalHistoryRootNode.class, "DateFolderName_5");                
                case 6: return NbBundle.getMessage(LocalHistoryRootNode.class, "DateFolderName_6");                                             
            }
            return NbBundle.getMessage(LocalHistoryRootNode.class, "DateFolderName_other");                
        }

        public int compareTo(Object obj) {
            if( !(obj instanceof DateFolderNode) || obj == null) {
                return -1;
            }
            DateFolderNode lhNode = (DateFolderNode) obj;        

            if(lhNode.getDay() > getDay()) {
                return -1;
            } else if(lhNode.getDay() < getDay()) {
                return 1;
            } else {
                return 0;
            }                    
        }
    }    
}

java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.