• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
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 
17 package com.android.ide.common.resources;
18 
19 import com.android.annotations.VisibleForTesting;
20 import com.android.annotations.VisibleForTesting.Visibility;
21 import com.android.ide.common.resources.configuration.Configurable;
22 import com.android.ide.common.resources.configuration.FolderConfiguration;
23 import com.android.io.IAbstractFile;
24 import com.android.io.IAbstractFolder;
25 import com.android.resources.FolderTypeRelationship;
26 import com.android.resources.ResourceFolderType;
27 import com.android.resources.ResourceType;
28 
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.List;
32 
33 /**
34  * Resource Folder class. Contains list of {@link ResourceFile}s,
35  * the {@link FolderConfiguration}, and a link to the {@link IAbstractFolder} object.
36  */
37 public final class ResourceFolder implements Configurable {
38     final ResourceFolderType mType;
39     final FolderConfiguration mConfiguration;
40     IAbstractFolder mFolder;
41     ArrayList<ResourceFile> mFiles = null;
42     private final ResourceRepository mRepository;
43 
44 
45     /**
46      * Creates a new {@link ResourceFolder}
47      * @param type The type of the folder
48      * @param config The configuration of the folder
49      * @param folder The associated {@link IAbstractFolder} object.
50      * @param repository The associated {@link ResourceRepository}
51      */
ResourceFolder(ResourceFolderType type, FolderConfiguration config, IAbstractFolder folder, ResourceRepository repository)52     protected ResourceFolder(ResourceFolderType type, FolderConfiguration config,
53             IAbstractFolder folder, ResourceRepository repository) {
54         mType = type;
55         mConfiguration = config;
56         mFolder = folder;
57         mRepository = repository;
58     }
59 
60     /**
61      * Processes a file and adds it to its parent folder resource.
62      *
63      * @param file the underlying resource file.
64      * @param kind the file change kind.
65      * @param context a context object with state for the current update, such
66      *            as a place to stash errors encountered
67      * @return the {@link ResourceFile} that was created.
68      */
processFile(IAbstractFile file, ResourceDeltaKind kind, ScanningContext context)69     public ResourceFile processFile(IAbstractFile file, ResourceDeltaKind kind,
70             ScanningContext context) {
71         // look for this file if it's already been created
72         ResourceFile resFile = getFile(file);
73 
74         if (resFile == null) {
75             if (kind != ResourceDeltaKind.REMOVED) {
76                 // create a ResourceFile for it.
77 
78                 // check if that's a single or multi resource type folder. For now we define this by
79                 // the number of possible resource type output by files in the folder.
80                 // We have a special case for layout/menu folders which can also generate IDs.
81                 // This does
82                 // not make the difference between several resource types from a single file or
83                 // the ability to have 2 files in the same folder generating 2 different types of
84                 // resource. The former is handled by MultiResourceFile properly while we don't
85                 // handle the latter. If we were to add this behavior we'd have to change this call.
86                 List<ResourceType> types = FolderTypeRelationship.getRelatedResourceTypes(mType);
87 
88                 if (types.size() == 1) {
89                     resFile = new SingleResourceFile(file, this);
90                 } else if (types.contains(ResourceType.LAYOUT)) {
91                     resFile = new IdGeneratingResourceFile(file, this, ResourceType.LAYOUT);
92                 } else if (types.contains(ResourceType.MENU)) {
93                     resFile = new IdGeneratingResourceFile(file, this, ResourceType.MENU);
94                 } else {
95                     resFile = new MultiResourceFile(file, this);
96                 }
97 
98                 resFile.load(context);
99 
100                 // add it to the folder
101                 addFile(resFile);
102             }
103         } else {
104             if (kind == ResourceDeltaKind.REMOVED) {
105                 removeFile(resFile, context);
106             } else {
107                 resFile.update(context);
108             }
109         }
110 
111         return resFile;
112     }
113 
114 
115     /**
116      * Adds a {@link ResourceFile} to the folder.
117      * @param file The {@link ResourceFile}.
118      */
119     @VisibleForTesting(visibility=Visibility.PROTECTED)
addFile(ResourceFile file)120     public void addFile(ResourceFile file) {
121         if (mFiles == null) {
122             mFiles = new ArrayList<ResourceFile>();
123         }
124 
125         mFiles.add(file);
126     }
127 
removeFile(ResourceFile file, ScanningContext context)128     protected void removeFile(ResourceFile file, ScanningContext context) {
129         file.dispose(context);
130         mFiles.remove(file);
131     }
132 
dispose(ScanningContext context)133     protected void dispose(ScanningContext context) {
134         if (mFiles != null) {
135             for (ResourceFile file : mFiles) {
136                 file.dispose(context);
137             }
138 
139             mFiles.clear();
140         }
141     }
142 
143     /**
144      * Returns the {@link IAbstractFolder} associated with this object.
145      */
getFolder()146     public IAbstractFolder getFolder() {
147         return mFolder;
148     }
149 
150     /**
151      * Returns the {@link ResourceFolderType} of this object.
152      */
getType()153     public ResourceFolderType getType() {
154         return mType;
155     }
156 
getRepository()157     public ResourceRepository getRepository() {
158         return mRepository;
159     }
160 
161     /**
162      * Returns the list of {@link ResourceType}s generated by the files inside this folder.
163      */
getResourceTypes()164     public Collection<ResourceType> getResourceTypes() {
165         ArrayList<ResourceType> list = new ArrayList<ResourceType>();
166 
167         if (mFiles != null) {
168             for (ResourceFile file : mFiles) {
169                 Collection<ResourceType> types = file.getResourceTypes();
170 
171                 // loop through those and add them to the main list,
172                 // if they are not already present
173                 for (ResourceType resType : types) {
174                     if (list.indexOf(resType) == -1) {
175                         list.add(resType);
176                     }
177                 }
178             }
179         }
180 
181         return list;
182     }
183 
184     @Override
getConfiguration()185     public FolderConfiguration getConfiguration() {
186         return mConfiguration;
187     }
188 
189     /**
190      * Returns whether the folder contains a file with the given name.
191      * @param name the name of the file.
192      */
hasFile(String name)193     public boolean hasFile(String name) {
194         return mFolder.hasFile(name);
195     }
196 
197     /**
198      * Returns the {@link ResourceFile} matching a {@link IAbstractFile} object.
199      * @param file The {@link IAbstractFile} object.
200      * @return the {@link ResourceFile} or null if no match was found.
201      */
getFile(IAbstractFile file)202     private ResourceFile getFile(IAbstractFile file) {
203         if (mFiles != null) {
204             for (ResourceFile f : mFiles) {
205                 if (f.getFile().equals(file)) {
206                     return f;
207                 }
208             }
209         }
210         return null;
211     }
212 
213     /**
214      * Returns the {@link ResourceFile} matching a given name.
215      * @param filename The name of the file to return.
216      * @return the {@link ResourceFile} or <code>null</code> if no match was found.
217      */
getFile(String filename)218     public ResourceFile getFile(String filename) {
219         if (mFiles != null) {
220             for (ResourceFile f : mFiles) {
221                 if (f.getFile().getName().equals(filename)) {
222                     return f;
223                 }
224             }
225         }
226         return null;
227     }
228 
229     /**
230      * Returns whether a file in the folder is generating a resource of a specified type.
231      * @param type The {@link ResourceType} being looked up.
232      */
hasResources(ResourceType type)233     public boolean hasResources(ResourceType type) {
234         // Check if the folder type is able to generate resource of the type that was asked.
235         // this is a first check to avoid going through the files.
236         List<ResourceFolderType> folderTypes = FolderTypeRelationship.getRelatedFolders(type);
237 
238         boolean valid = false;
239         for (ResourceFolderType rft : folderTypes) {
240             if (rft == mType) {
241                 valid = true;
242                 break;
243             }
244         }
245 
246         if (valid) {
247             if (mFiles != null) {
248                 for (ResourceFile f : mFiles) {
249                     if (f.hasResources(type)) {
250                         return true;
251                     }
252                 }
253             }
254         }
255         return false;
256     }
257 
258     @Override
toString()259     public String toString() {
260         return mFolder.toString();
261     }
262 }
263