/* * Copyright 2012 Sebastian Annies, Hamburg * * 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.googlecode.mp4parser.util; import com.coremedia.iso.IsoFile; import com.coremedia.iso.boxes.Box; import com.coremedia.iso.boxes.ContainerBox; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Path { private Path() { } static Pattern component = Pattern.compile("(....|\\.\\.)(\\[(.*)\\])?"); public static String createPath(Box box) { return createPath(box, ""); } private static String createPath(Box box, String path) { if (box instanceof IsoFile) { return path; } else { List boxesOfBoxType = box.getParent().getBoxes(box.getClass()); int index = boxesOfBoxType.indexOf(box); path = String.format("/%s[%d]", box.getType(), index) + path; return createPath(box.getParent(), path); } } public static Box getPath(Box box, String path) { List all = getPaths(box, path); return all.isEmpty() ? null : all.get(0); } public static List getPaths(Box box, String path) { if (path.startsWith("/")) { Box isoFile = box; while (isoFile.getParent() != null) { isoFile = isoFile.getParent(); } assert isoFile instanceof IsoFile : isoFile.getType() + " has no parent"; return getPaths(isoFile, path.substring(1)); } else if (path.isEmpty()) { return Collections.singletonList(box); } else { String later; String now; if (path.contains("/")) { later = path.substring(path.indexOf('/') + 1); now = path.substring(0, path.indexOf('/')); } else { now = path; later = ""; } Matcher m = component.matcher(now); if (m.matches()) { String type = m.group(1); if ("..".equals(type)) { return getPaths(box.getParent(), later); } else { int index = -1; if (m.group(2) != null) { // we have a specific index String indexString = m.group(3); index = Integer.parseInt(indexString); } List children = new LinkedList(); int currentIndex = 0; for (Box box1 : ((ContainerBox) box).getBoxes()) { if (box1.getType().matches(type)) { if (index == -1 || index == currentIndex) { children.addAll(getPaths(box1, later)); } currentIndex++; } } return children; } } else { throw new RuntimeException(now + " is invalid path."); } } } public static boolean isContained(Box box, String path) { assert path.startsWith("/") : "Absolute path required"; return getPaths(box, path).contains(box); } }