diff options
Diffstat (limited to 'src/com/android/gallery3d/data/Path.java')
-rw-r--r-- | src/com/android/gallery3d/data/Path.java | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/data/Path.java b/src/com/android/gallery3d/data/Path.java new file mode 100644 index 000000000..fcae65e66 --- /dev/null +++ b/src/com/android/gallery3d/data/Path.java @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.data; + +import com.android.gallery3d.common.Utils; +import com.android.gallery3d.util.IdentityCache; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; + +public class Path { + private static final String TAG = "Path"; + private static Path sRoot = new Path(null, "ROOT"); + + private final Path mParent; + private final String mSegment; + private WeakReference<MediaObject> mObject; + private IdentityCache<String, Path> mChildren; + + private Path(Path parent, String segment) { + mParent = parent; + mSegment = segment; + } + + public Path getChild(String segment) { + synchronized (Path.class) { + if (mChildren == null) { + mChildren = new IdentityCache<String, Path>(); + } else { + Path p = mChildren.get(segment); + if (p != null) return p; + } + + Path p = new Path(this, segment); + mChildren.put(segment, p); + return p; + } + } + + public Path getParent() { + synchronized (Path.class) { + return mParent; + } + } + + public Path getChild(int segment) { + return getChild(String.valueOf(segment)); + } + + public Path getChild(long segment) { + return getChild(String.valueOf(segment)); + } + + public void setObject(MediaObject object) { + synchronized (Path.class) { + Utils.assertTrue(mObject == null || mObject.get() == null); + mObject = new WeakReference<MediaObject>(object); + } + } + + MediaObject getObject() { + synchronized (Path.class) { + return (mObject == null) ? null : mObject.get(); + } + } + + @Override + // TODO: toString() should be more efficient, will fix it later + public String toString() { + synchronized (Path.class) { + StringBuilder sb = new StringBuilder(); + String[] segments = split(); + for (int i = 0; i < segments.length; i++) { + sb.append("/"); + sb.append(segments[i]); + } + return sb.toString(); + } + } + + public boolean equalsIgnoreCase (String p) { + String path = toString(); + return path.equalsIgnoreCase(p); + } + + public static Path fromString(String s) { + synchronized (Path.class) { + String[] segments = split(s); + Path current = sRoot; + for (int i = 0; i < segments.length; i++) { + current = current.getChild(segments[i]); + } + return current; + } + } + + public String[] split() { + synchronized (Path.class) { + int n = 0; + for (Path p = this; p != sRoot; p = p.mParent) { + n++; + } + String[] segments = new String[n]; + int i = n - 1; + for (Path p = this; p != sRoot; p = p.mParent) { + segments[i--] = p.mSegment; + } + return segments; + } + } + + public static String[] split(String s) { + int n = s.length(); + if (n == 0) return new String[0]; + if (s.charAt(0) != '/') { + throw new RuntimeException("malformed path:" + s); + } + ArrayList<String> segments = new ArrayList<String>(); + int i = 1; + while (i < n) { + int brace = 0; + int j; + for (j = i; j < n; j++) { + char c = s.charAt(j); + if (c == '{') ++brace; + else if (c == '}') --brace; + else if (brace == 0 && c == '/') break; + } + if (brace != 0) { + throw new RuntimeException("unbalanced brace in path:" + s); + } + segments.add(s.substring(i, j)); + i = j + 1; + } + String[] result = new String[segments.size()]; + segments.toArray(result); + return result; + } + + // Splits a string to an array of strings. + // For example, "{foo,bar,baz}" -> {"foo","bar","baz"}. + public static String[] splitSequence(String s) { + int n = s.length(); + if (s.charAt(0) != '{' || s.charAt(n-1) != '}') { + throw new RuntimeException("bad sequence: " + s); + } + ArrayList<String> segments = new ArrayList<String>(); + int i = 1; + while (i < n - 1) { + int brace = 0; + int j; + for (j = i; j < n - 1; j++) { + char c = s.charAt(j); + if (c == '{') ++brace; + else if (c == '}') --brace; + else if (brace == 0 && c == ',') break; + } + if (brace != 0) { + throw new RuntimeException("unbalanced brace in path:" + s); + } + segments.add(s.substring(i, j)); + i = j + 1; + } + String[] result = new String[segments.size()]; + segments.toArray(result); + return result; + } + + public String getPrefix() { + if (this == sRoot) return ""; + return getPrefixPath().mSegment; + } + + public Path getPrefixPath() { + synchronized (Path.class) { + Path current = this; + if (current == sRoot) { + throw new IllegalStateException(); + } + while (current.mParent != sRoot) { + current = current.mParent; + } + return current; + } + } + + public String getSuffix() { + // We don't need lock because mSegment is final. + return mSegment; + } + + // Below are for testing/debugging only + static void clearAll() { + synchronized (Path.class) { + sRoot = new Path(null, ""); + } + } + + static void dumpAll() { + dumpAll(sRoot, "", ""); + } + + static void dumpAll(Path p, String prefix1, String prefix2) { + synchronized (Path.class) { + MediaObject obj = p.getObject(); + Log.d(TAG, prefix1 + p.mSegment + ":" + + (obj == null ? "null" : obj.getClass().getSimpleName())); + if (p.mChildren != null) { + ArrayList<String> childrenKeys = p.mChildren.keys(); + int i = 0, n = childrenKeys.size(); + for (String key : childrenKeys) { + Path child = p.mChildren.get(key); + if (child == null) { + ++i; + continue; + } + Log.d(TAG, prefix2 + "|"); + if (++i < n) { + dumpAll(child, prefix2 + "+-- ", prefix2 + "| "); + } else { + dumpAll(child, prefix2 + "+-- ", prefix2 + " "); + } + } + } + } + } +} |