1/* 2 * Copyright 2012 Sebastian Annies, Hamburg 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 */ 16package com.googlecode.mp4parser.util; 17 18 19import com.coremedia.iso.IsoFile; 20import com.coremedia.iso.boxes.Box; 21import com.coremedia.iso.boxes.ContainerBox; 22 23import java.util.Collections; 24import java.util.LinkedList; 25import java.util.List; 26import java.util.regex.Matcher; 27import java.util.regex.Pattern; 28 29public class Path { 30 31 private Path() { 32 } 33 34 static Pattern component = Pattern.compile("(....|\\.\\.)(\\[(.*)\\])?"); 35 36 public static String createPath(Box box) { 37 return createPath(box, ""); 38 } 39 40 private static String createPath(Box box, String path) { 41 if (box instanceof IsoFile) { 42 return path; 43 } else { 44 List<?> boxesOfBoxType = box.getParent().getBoxes(box.getClass()); 45 int index = boxesOfBoxType.indexOf(box); 46 path = String.format("/%s[%d]", box.getType(), index) + path; 47 48 return createPath(box.getParent(), path); 49 } 50 } 51 52 public static Box getPath(Box box, String path) { 53 List<Box> all = getPaths(box, path); 54 return all.isEmpty() ? null : all.get(0); 55 } 56 57 58 public static List<Box> getPaths(Box box, String path) { 59 if (path.startsWith("/")) { 60 Box isoFile = box; 61 while (isoFile.getParent() != null) { 62 isoFile = isoFile.getParent(); 63 } 64 assert isoFile instanceof IsoFile : isoFile.getType() + " has no parent"; 65 return getPaths(isoFile, path.substring(1)); 66 } else if (path.isEmpty()) { 67 return Collections.singletonList(box); 68 } else { 69 String later; 70 String now; 71 if (path.contains("/")) { 72 later = path.substring(path.indexOf('/') + 1); 73 now = path.substring(0, path.indexOf('/')); 74 } else { 75 now = path; 76 later = ""; 77 } 78 79 Matcher m = component.matcher(now); 80 if (m.matches()) { 81 String type = m.group(1); 82 if ("..".equals(type)) { 83 return getPaths(box.getParent(), later); 84 } else { 85 int index = -1; 86 if (m.group(2) != null) { 87 // we have a specific index 88 String indexString = m.group(3); 89 index = Integer.parseInt(indexString); 90 } 91 List<Box> children = new LinkedList<Box>(); 92 int currentIndex = 0; 93 for (Box box1 : ((ContainerBox) box).getBoxes()) { 94 if (box1.getType().matches(type)) { 95 if (index == -1 || index == currentIndex) { 96 children.addAll(getPaths(box1, later)); 97 } 98 currentIndex++; 99 } 100 } 101 return children; 102 } 103 } else { 104 throw new RuntimeException(now + " is invalid path."); 105 } 106 } 107 108 } 109 110 111 public static boolean isContained(Box box, String path) { 112 assert path.startsWith("/") : "Absolute path required"; 113 return getPaths(box, path).contains(box); 114 } 115} 116