Home | History | Annotate | Download | only in templates
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.ide.eclipse.adt.internal.wizards.templates;
     17 
     18 import static com.android.SdkConstants.FD_EXTRAS;
     19 import static com.android.SdkConstants.FD_TEMPLATES;
     20 import static com.android.SdkConstants.FD_TOOLS;
     21 import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.TEMPLATE_XML;
     22 
     23 import com.android.annotations.NonNull;
     24 import com.android.annotations.Nullable;
     25 import com.android.ide.eclipse.adt.AdtPlugin;
     26 import com.android.ide.eclipse.adt.AdtUtils;
     27 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
     28 import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
     29 import com.google.common.base.Charsets;
     30 import com.google.common.collect.Maps;
     31 import com.google.common.collect.Sets;
     32 import com.google.common.io.Files;
     33 
     34 import org.w3c.dom.Document;
     35 
     36 import java.io.File;
     37 import java.io.IOException;
     38 import java.util.ArrayList;
     39 import java.util.Collections;
     40 import java.util.Comparator;
     41 import java.util.List;
     42 import java.util.Map;
     43 import java.util.Set;
     44 
     45 /** Handles locating templates and providing template metadata */
     46 public class TemplateManager {
     47 	private static final Set<String> EXCLUDED_CATEGORIES = Sets.newHashSet("Folder", "Google");
     48 	private static final Set<String> EXCLUDED_FORMFACTORS = Sets.newHashSet("Wear", "TV");
     49 
     50     TemplateManager() {
     51     }
     52 
     53     /** @return the root folder containing templates */
     54     @Nullable
     55     public static File getTemplateRootFolder() {
     56         String location = AdtPrefs.getPrefs().getOsSdkFolder();
     57         if (location != null) {
     58             File folder = new File(location, FD_TOOLS + File.separator + FD_TEMPLATES);
     59             if (folder.isDirectory()) {
     60                 return folder;
     61             }
     62         }
     63 
     64         return null;
     65     }
     66 
     67     /** @return the root folder containing extra templates */
     68     @NonNull
     69     public static List<File> getExtraTemplateRootFolders() {
     70         List<File> folders = new ArrayList<File>();
     71         String location = AdtPrefs.getPrefs().getOsSdkFolder();
     72         if (location != null) {
     73             File extras = new File(location, FD_EXTRAS);
     74             if (extras.isDirectory()) {
     75                 for (File vendor : AdtUtils.listFiles(extras)) {
     76                     if (!vendor.isDirectory()) {
     77                         continue;
     78                     }
     79                     for (File pkg : AdtUtils.listFiles(vendor)) {
     80                         if (pkg.isDirectory()) {
     81                             File folder = new File(pkg, FD_TEMPLATES);
     82                             if (folder.isDirectory()) {
     83                                 folders.add(folder);
     84                             }
     85                         }
     86                     }
     87                 }
     88 
     89                 // Legacy
     90                 File folder = new File(extras, FD_TEMPLATES);
     91                 if (folder.isDirectory()) {
     92                     folders.add(folder);
     93                 }
     94             }
     95         }
     96 
     97         return folders;
     98     }
     99 
    100     /**
    101      * Returns a template file under the given root, if it exists
    102      *
    103      * @param root the root folder
    104      * @param relativePath the relative path
    105      * @return a template file under the given root, if it exists
    106      */
    107     @Nullable
    108     public static File getTemplateLocation(@NonNull File root, @NonNull String relativePath) {
    109         File templateRoot = getTemplateRootFolder();
    110         if (templateRoot != null) {
    111             String rootPath = root.getPath();
    112             File templateFile = new File(templateRoot,
    113                     rootPath.replace('/', File.separatorChar) + File.separator
    114                     + relativePath.replace('/', File.separatorChar));
    115             if (templateFile.exists()) {
    116                 return templateFile;
    117             }
    118         }
    119 
    120         return null;
    121     }
    122 
    123     /**
    124      * Returns a template file under one of the available roots, if it exists
    125      *
    126      * @param relativePath the relative path
    127      * @return a template file under one of the available roots, if it exists
    128      */
    129     @Nullable
    130     public static File getTemplateLocation(@NonNull String relativePath) {
    131         File templateRoot = getTemplateRootFolder();
    132         if (templateRoot != null) {
    133             File templateFile = new File(templateRoot,
    134                     relativePath.replace('/', File.separatorChar));
    135             if (templateFile.exists()) {
    136                 return templateFile;
    137             }
    138         }
    139 
    140         return null;
    141 
    142     }
    143 
    144     /**
    145      * Returns all the templates with the given prefix
    146      *
    147      * @param folder the folder prefix
    148      * @return the available templates
    149      */
    150     @NonNull
    151     List<File> getTemplates(@NonNull String folder) {
    152         List<File> templates = new ArrayList<File>();
    153         Map<String, File> templateNames = Maps.newHashMap();
    154         File root = getTemplateRootFolder();
    155         if (root != null) {
    156             File[] files = new File(root, folder).listFiles();
    157             if (files != null) {
    158                 for (File file : files) {
    159                     if (file.isDirectory()) { // Avoid .DS_Store etc
    160                         templates.add(file);
    161                         templateNames.put(file.getName(), file);
    162                     }
    163                 }
    164             }
    165         }
    166 
    167         // Add in templates from extras/ as well.
    168         for (File extra : getExtraTemplateRootFolders()) {
    169             File[] files = new File(extra, folder).listFiles();
    170             if (files != null) {
    171                 for (File file : files) {
    172                     if (file.isDirectory()) {
    173                         File replaces = templateNames.get(file.getName());
    174                         if (replaces != null) {
    175                             int compare = compareTemplates(replaces, file);
    176                             if (compare > 0) {
    177                                 int index = templates.indexOf(replaces);
    178                                 if (index != -1) {
    179                                     templates.set(index, file);
    180                                 } else {
    181                                     templates.add(file);
    182                                 }
    183                             }
    184                         } else {
    185                             templates.add(file);
    186                         }
    187                     }
    188                 }
    189             }
    190         }
    191 
    192         // Sort by file name (not path as is File's default)
    193         if (templates.size() > 1) {
    194             Collections.sort(templates, new Comparator<File>() {
    195                 @Override
    196                 public int compare(File file1, File file2) {
    197                     return file1.getName().compareTo(file2.getName());
    198                 }
    199             });
    200         }
    201 
    202         return templates;
    203     }
    204 
    205     /**
    206      * Compare two files, and return the one with the HIGHEST revision, and if
    207      * the same, most recently modified
    208      */
    209     private int compareTemplates(File file1, File file2) {
    210         TemplateMetadata template1 = getTemplate(file1);
    211         TemplateMetadata template2 = getTemplate(file2);
    212 
    213         if (template1 == null) {
    214             return 1;
    215         } else if (template2 == null) {
    216             return -1;
    217         } else {
    218             int delta = template2.getRevision() - template1.getRevision();
    219             if (delta == 0) {
    220                 delta = (int) (file2.lastModified() - file1.lastModified());
    221             }
    222             return delta;
    223         }
    224     }
    225 
    226     /** Cache for {@link #getTemplate()} */
    227     private Map<File, TemplateMetadata> mTemplateMap;
    228 
    229     @Nullable
    230     TemplateMetadata getTemplate(File templateDir) {
    231         if (mTemplateMap != null) {
    232             TemplateMetadata metadata = mTemplateMap.get(templateDir);
    233             if (metadata != null) {
    234                 return metadata;
    235             }
    236         } else {
    237             mTemplateMap = Maps.newHashMap();
    238         }
    239 
    240         try {
    241             File templateFile = new File(templateDir, TEMPLATE_XML);
    242             if (templateFile.isFile()) {
    243                 String xml = Files.toString(templateFile, Charsets.UTF_8);
    244                 Document doc = DomUtilities.parseDocument(xml, true);
    245                 if (doc != null && doc.getDocumentElement() != null) {
    246                     TemplateMetadata metadata = new TemplateMetadata(doc);
    247                     if (EXCLUDED_CATEGORIES.contains(metadata.getCategory()) ||
    248                     	EXCLUDED_FORMFACTORS.contains(metadata.getFormFactor())) {
    249                     	return null;
    250                     }
    251                     mTemplateMap.put(templateDir, metadata);
    252                     return metadata;
    253                 }
    254             }
    255         } catch (IOException e) {
    256             AdtPlugin.log(e, null);
    257         }
    258 
    259         return null;
    260     }
    261 }
    262