/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.sling.ide.transport; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * The <tt>ResourceProxy</tt> is a representation of a resource as found in the local workspace * * <p> * The resource usually has properties, as returned from <tt>{@link #getProperties()}</tt>. If no properties are found, * it means that the resource is only a reference and not that it is an empty resource. * If a property contains multiple values it is being represented by an array type. * </p> * * <p> * The resource only has information about the first row of children, as returned by {@link #getChildren()}. It does not * necessarily know about second-level children. * </p> * * <p> * By exception, if the child is <tt>covered</tt>, then all information about that child and its descendants is known. * </p> * */ public class ResourceProxy { private final String path; private final Map<String, Object> properties; private final List<ResourceProxy> children = new ArrayList<>(); private final Map<Class<?>, Object> adapted = new HashMap<>(1); public ResourceProxy(String path) { this(path, new HashMap<String, Object>()); } public ResourceProxy(String path, Map<String, Object> properties) { this.path = path; this.properties = properties; } public void addChild(ResourceProxy child) { // TODO - should validate for direct parent if (!isParent(path, child.getPath())) { throw new IllegalArgumentException("Resource at path " + child.getPath() + " is not a direct child of " + path); } this.children.add(child); } public void addProperty(String name, Object value) { this.properties.put(name, value); } public String getPath() { return path; } public List<ResourceProxy> getChildren() { return children; } public Map<String, Object> getProperties() { return properties; } public <T> void addAdapted(Class<T> klazz, T adaptedInstance) { adapted.put(klazz, adaptedInstance); } public <T> T adaptTo(Class<T> klazz) { // OK to suppress warnings since type safety is insured by addAdapted @SuppressWarnings("unchecked") T res = (T) adapted.get(klazz); return res; } public List<ResourceProxy> getCoveredChildren() { List<ResourceProxy> coveredChildren = new ArrayList<>(); for (ResourceProxy child : getChildren()) { if (child.getProperties().isEmpty()) { continue; } coveredChildren.add(child); } return coveredChildren; } public boolean covers(String path) { for (ResourceProxy child : getCoveredChildren()) { if (child.getPath().equals(path)) { return true; } else if (isDescendent(child.getPath(), path)) { return child.covers(path); } } return false; } private boolean isParent(String parentPath, String childPath) { if (!isDescendent(parentPath, childPath)) { return false; } for (int i = parentPath.length() + 1; i < childPath.length(); i++) { if (childPath.charAt(i) == '/') { return false; } } return true; } private boolean isDescendent(String parentPath, String childPath) { if (parentPath.equals("/")) { return childPath.length() > 1; } return parentPath.length() < childPath.length() && childPath.charAt(parentPath.length()) == '/' && childPath.startsWith(parentPath); } public ResourceProxy getChild(String path) { for (ResourceProxy child : getChildren()) { if (child.getPath().equals(path)) { return child; } else if (isDescendent(child.getPath(), path)) { return child.getChild(path); } } return null; } @Override public String toString() { return toString0(1); } private String toString0(int padding) { StringBuilder out = new StringBuilder(); out.append(getClass().getSimpleName()).append(": path=").append(path).append(", properties=") .append(properties); for (ResourceProxy child : children) { out.append("\n"); for (int i = 0; i < padding * 2; i++) { out.append(' '); } out.append(child.toString0(padding + 1)); } return out.toString(); } }