package net.sourceforge.fenixedu.domain.contents;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import net.sourceforge.fenixedu.domain.FileContent;
import net.sourceforge.fenixedu.domain.functionalities.AvailabilityPolicy;
import net.sourceforge.fenixedu.domain.functionalities.Functionality;
/**
* A Container
is a composed content, that is, a grouping of other
* contents under a certain prefix or context. Containers can have the same
* information as other basic contentes but are usually important due to their
* structure and not their name or body.
*
* @author cfgi
* @author lpec
* @author pcma
*/
public abstract class Container extends Container_Base {
public Container() {
super();
}
public boolean isChildAccepted(Content child) {
return true;
}
@Override
public boolean isParentAccepted(Container parent) {
return true;
}
public Collection getOrderedDirectChildren() {
return getOrderedChildrenNodes();
}
public Collection getDirectChildrenAsContent() {
return getChildrenAsContent();
}
public Collection getChildrenAsContent() {
List children = new ArrayList();
for (Node node : getOrderedChildrenNodes()) {
children.add(node.getChild());
}
return children;
}
public Collection getChildren(Class type) {
List children = new ArrayList();
for (Node node : getChildren()) {
T parent = (T) node.getChild();
if (type != null && !type.isAssignableFrom(parent.getClass())) {
continue;
}
children.add(parent);
}
return children;
}
public Collection getOrderedChildren(Class type) {
List contents = new ArrayList();
for (Node node : getOrderedChildrenNodes()) {
T parent = (T) node.getChild();
if (type != null && !type.isAssignableFrom(parent.getClass())) {
continue;
}
contents.add(parent);
}
return contents;
}
public Collection getOrderedChildren(final Class... types) {
final List contents = new ArrayList();
for (final Node node : getOrderedChildrenNodes()) {
final Content child = node.getChild();
if (isContentAssinableTo(child, types)) {
contents.add(child);
}
}
return contents;
}
private boolean isContentAssinableTo(Content content, Class... types) {
final Class clazz = content.getClass();
for (final Class typeClass : types) {
if (typeClass.isAssignableFrom(clazz)) {
return true;
}
}
return false;
}
public Collection getOrderedChildrenNodes() {
return new TreeSet(getChildren());
}
public Collection getOrderedChildrenNodes(Class extends Content> childType) {
Set nodes = new TreeSet();
for (Node node : getOrderedChildrenNodes()) {
if (childType.isAssignableFrom(node.getChild().getClass())) {
nodes.add(node);
}
}
return nodes;
}
private List getPathTo(Content topContent, Content bottomContent) {
if (topContent == bottomContent) {
List contents = new ArrayList();
contents.add((Content) bottomContent);
return contents;
}
for (Node node : bottomContent.getParents()) {
Container content = node.getParent();
List result = content.getPathTo(topContent, content);
if (!result.isEmpty()) {
result.add(bottomContent);
return result;
}
}
return Collections.emptyList();
}
public List getPathTo(Content target) {
return getPathTo(this, target);
}
@Override
protected void disconnect() {
super.disconnect();
for (Node node : getChildren()) {
removeNode(node);
}
final Content content = getInitialContent();
if (content != null) {
removeInitialContent();
if (!content.hasAnyParents()) {
content.delete();
}
}
}
@Override
public Collection getMenu() {
return isContainerMaximizable() ? new ArrayList() : new ArrayList(getOrderedChildrenNodes());
}
public Content getChildByContentId(String id) {
for (Content child : getChildrenAsContent()) {
if (id.equals(child.getContentId())) {
return child;
}
}
return null;
}
@Override
public boolean isContainer() {
return true;
}
@Override
public boolean isElement() {
return false;
}
public boolean isContainerMaximizable() {
return Boolean.TRUE.equals(getMaximizable());
}
protected String getSubPathForSearch(final String path) {
final int indexOfSlash = path.indexOf('/');
return indexOfSlash >= 0 ? path.substring(0, indexOfSlash) : path;
}
public void addPathContentsForTrailingPath(final List contents, final String trailingPath) {
int contentsSize = contents.size();
for (final Node node : getChildren()) {
final Content content = node.getChild();
content.addPathContents(contents, trailingPath);
if (contentsSize < contents.size()) {
return;
}
}
if (getParentsSet().isEmpty()
&& !(trailingPath.length() == 0 || (trailingPath.length() == 1 && trailingPath.charAt(0) == '/'))) {
throw new InvalidContentPathException(this, trailingPath);
}
}
@Override
public void addPathContents(final List contents, final String path) {
final String subPath = getSubPathForSearch(path);
if (matchesPath(subPath)) {
contents.add(this);
if (subPath.length() + 1 < path.length()) {
final String trailingPath = path.substring(subPath.length() + 1);
final int size = contents.size();
addPathContentsForTrailingPath(contents, trailingPath);
if (contents.size() == size
&& !(trailingPath.length() == 0 || (trailingPath.length() == 1 && trailingPath.charAt(0) == '/'))) {
throw new InvalidContentPathException(this, trailingPath);
}
}
}
}
@Override
public AvailabilityPolicy getAvailabilityPolicy() {
AvailabilityPolicy policy = super.getAvailabilityPolicy();
if (policy != null) {
return policy;
}
// Collection nodes = getOrderedChildrenNodes();
Collection nodes = getChildrenSet();
return nodes.isEmpty() ? null : nodes.iterator().next().getChild().getAvailabilityPolicy();
}
public void addChild(final Content content) {
createChildNode(content instanceof Functionality ? new FunctionalityCall((Functionality) content) : content);
}
protected abstract Node createChildNode(final Content childContent);
public void removeChild(final Content content) {
for (Node node : getChildrenSet()) {
if (node.getChild() == content) {
removeNode(node);
break;
}
}
}
protected void removeNode(Node node) {
Content content = node.getChild();
if (getInitialContent() == content) {
setInitialContent(null);
}
node.delete();
if (!content.hasAnyParents()) {
content.delete();
}
}
public Node getChildNode(Content content) {
for (Node node : getChildren()) {
if (node.getChild() == content) {
return node;
}
}
return null;
}
@Override
public Content getInitialContent() {
Content content = super.getInitialContent();
if (content != null) {
return content;
}
final Collection elements = (Collection) getOrderedChildren(Element.class);
return elements.isEmpty() ? null : elements.iterator().next();
}
public void addFile(final FileContent fileContent) {
addChild(new Attachment(fileContent));
}
}