1 /*
2  * Copyright (C) 2013 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.documentsui.model;
18 
19 import android.content.ContentResolver;
20 import android.provider.DocumentsProvider;
21 
22 import java.io.DataInputStream;
23 import java.io.DataOutputStream;
24 import java.io.FileNotFoundException;
25 import java.io.IOException;
26 import java.net.ProtocolException;
27 import java.util.Collection;
28 import java.util.LinkedList;
29 
30 /**
31  * Representation of a stack of {@link DocumentInfo}, usually the result of a
32  * user-driven traversal.
33  */
34 public class DocumentStack extends LinkedList<DocumentInfo> implements Durable {
35     private static final int VERSION_INIT = 1;
36     private static final int VERSION_ADD_ROOT = 2;
37 
38     public RootInfo root;
39 
getTitle()40     public String getTitle() {
41         if (size() == 1 && root != null) {
42             return root.title;
43         } else if (size() > 1) {
44             return peek().displayName;
45         } else {
46             return null;
47         }
48     }
49 
isRecents()50     public boolean isRecents() {
51         return size() == 0;
52     }
53 
updateRoot(Collection<RootInfo> matchingRoots)54     public void updateRoot(Collection<RootInfo> matchingRoots) throws FileNotFoundException {
55         for (RootInfo root : matchingRoots) {
56             if (root.equals(this.root)) {
57                 this.root = root;
58                 return;
59             }
60         }
61         throw new FileNotFoundException("Failed to find matching root for " + root);
62     }
63 
64     /**
65      * Update a possibly stale restored stack against a live
66      * {@link DocumentsProvider}.
67      */
updateDocuments(ContentResolver resolver)68     public void updateDocuments(ContentResolver resolver) throws FileNotFoundException {
69         for (DocumentInfo info : this) {
70             info.updateSelf(resolver);
71         }
72     }
73 
74     /**
75      * Build key that uniquely identifies this stack. It omits most of the raw
76      * details included in {@link #write(DataOutputStream)}, since they change
77      * too regularly to be used as a key.
78      */
buildKey()79     public String buildKey() {
80         final StringBuilder builder = new StringBuilder();
81         if (root != null) {
82             builder.append(root.authority).append('#');
83             builder.append(root.rootId).append('#');
84         } else {
85             builder.append("[null]").append('#');
86         }
87         for (DocumentInfo doc : this) {
88             builder.append(doc.documentId).append('#');
89         }
90         return builder.toString();
91     }
92 
93     @Override
reset()94     public void reset() {
95         clear();
96         root = null;
97     }
98 
99     @Override
read(DataInputStream in)100     public void read(DataInputStream in) throws IOException {
101         final int version = in.readInt();
102         switch (version) {
103             case VERSION_INIT:
104                 throw new ProtocolException("Ignored upgrade");
105             case VERSION_ADD_ROOT:
106                 if (in.readBoolean()) {
107                     root = new RootInfo();
108                     root.read(in);
109                 }
110                 final int size = in.readInt();
111                 for (int i = 0; i < size; i++) {
112                     final DocumentInfo doc = new DocumentInfo();
113                     doc.read(in);
114                     add(doc);
115                 }
116                 break;
117             default:
118                 throw new ProtocolException("Unknown version " + version);
119         }
120     }
121 
122     @Override
write(DataOutputStream out)123     public void write(DataOutputStream out) throws IOException {
124         out.writeInt(VERSION_ADD_ROOT);
125         if (root != null) {
126             out.writeBoolean(true);
127             root.write(out);
128         } else {
129             out.writeBoolean(false);
130         }
131         final int size = size();
132         out.writeInt(size);
133         for (int i = 0; i < size; i++) {
134             final DocumentInfo doc = get(i);
135             doc.write(out);
136         }
137     }
138 }
139