001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.lenya.cms.site;
020:
021: import java.util.Arrays;
022: import java.util.Comparator;
023:
024: import org.apache.avalon.framework.logger.AbstractLogEnabled;
025: import org.apache.avalon.framework.service.ServiceException;
026: import org.apache.avalon.framework.service.ServiceManager;
027: import org.apache.avalon.framework.service.Serviceable;
028: import org.apache.lenya.cms.publication.DocumentFactory;
029:
030: /**
031: * Abstract base class for site managers.
032: *
033: * @version $Id: AbstractSiteManager.java 473861 2006-11-12 03:51:14Z gregor $
034: */
035: public abstract class AbstractSiteManager extends AbstractLogEnabled
036: implements SiteManager, Serviceable {
037:
038: protected ServiceManager manager;
039:
040: /**
041: * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
042: */
043: public void service(ServiceManager manager) throws ServiceException {
044: this .manager = manager;
045: }
046:
047: /**
048: * Ctor.
049: * @param manager The service manager.
050: */
051: public AbstractSiteManager() {
052: }
053:
054: /**
055: * @see org.apache.lenya.cms.site.SiteManager#sortAscending(org.apache.lenya.cms.publication.util.DocumentSet)
056: */
057: public SiteNode[] sortAscending(SiteNode[] nodes)
058: throws SiteException {
059: if (nodes.length > 0) {
060:
061: DocumentFactory map = nodes[0].getStructure()
062: .getPublication().getFactory();
063: if (!check(map, new NodeSet(this .manager, nodes))) {
064: throw new SiteException(
065: "The dependence relation is not a strict partial order!");
066: }
067:
068: SiteNode[] sortedNodes = (SiteNode[]) Arrays.asList(nodes)
069: .toArray(new SiteNode[nodes.length]);
070: Arrays.sort(sortedNodes, new NodeComparator(map));
071: return sortedNodes;
072: } else {
073: return nodes;
074: }
075: }
076:
077: /**
078: * Checks if the dependence relation is a strict partial order.
079: *
080: * @param map The identity map to operate on.
081: * @param set The document set to check.
082: * @return A boolean value.
083: * @throws SiteException when something went wrong.
084: */
085: protected boolean check(DocumentFactory map, NodeSet set)
086: throws SiteException {
087: boolean isStrictPartialOrder = isIrreflexive(map, set)
088: && isAntisymmetric(map, set) && isTransitive(map, set);
089: return isStrictPartialOrder;
090: }
091:
092: /**
093: * Checks if the dependence relation is antisymmetric.
094: *
095: * @param map The identity map to operate on.
096: * @param set The document set to check.
097: * @return A boolean value.
098: * @throws SiteException when something went wrong.
099: */
100: protected boolean isAntisymmetric(DocumentFactory map, NodeSet set)
101: throws SiteException {
102: SiteNode[] resources = set.getNodes();
103: boolean isAntisymmetric = true;
104: for (int i = 0; i < resources.length; i++) {
105: for (int j = i + 1; j < resources.length; j++) {
106: if (requires(map, resources[i], resources[j])
107: && requires(map, resources[j], resources[i])
108: && !(resources[i] == resources[j])) {
109: isAntisymmetric = false;
110: }
111: }
112: }
113: return isAntisymmetric;
114: }
115:
116: /**
117: * Checks if the dependence relation is transitive.
118: *
119: * @param map The identity map to operate on.
120: * @param set The document set to check.
121: * @return A boolean value.
122: * @throws SiteException when something went wrong.
123: */
124: protected boolean isTransitive(DocumentFactory map, NodeSet set)
125: throws SiteException {
126: SiteNode[] resources = set.getNodes();
127: boolean isTransitive = true;
128: for (int i = 0; i < resources.length; i++) {
129: for (int j = i + 1; j < resources.length; j++) {
130: for (int k = j + 1; k < resources.length; k++) {
131: if (requires(map, resources[i], resources[j])
132: && requires(map, resources[j], resources[k])
133: && !requires(map, resources[i],
134: resources[k])) {
135: isTransitive = false;
136: }
137: }
138: }
139: }
140: return isTransitive;
141: }
142:
143: /**
144: * Checks if the dependence relation is irreflexive.
145: *
146: * @param map The identity map to operate on.
147: * @param set The document set.
148: * @return A boolean value
149: * @throws SiteException
150: */
151: protected boolean isIrreflexive(DocumentFactory map, NodeSet set)
152: throws SiteException {
153: SiteNode[] resources = set.getNodes();
154: boolean isIrreflexive = true;
155: for (int i = 0; i < resources.length; i++) {
156: if (requires(map, resources[i], resources[i])) {
157: isIrreflexive = false;
158: }
159: }
160: return isIrreflexive;
161: }
162:
163: /**
164: * Compares nodes according to the dependence relation.
165: */
166: public class NodeComparator implements Comparator {
167:
168: /**
169: * Ctor.
170: *
171: * @param map The identity map to operate on.
172: */
173: public NodeComparator(DocumentFactory map) {
174: this .map = map;
175: }
176:
177: private DocumentFactory map;
178:
179: /**
180: * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
181: */
182: public int compare(Object arg0, Object arg1) {
183: int result = 0;
184: if (arg0 instanceof SiteNode && arg1 instanceof SiteNode) {
185: SiteNode doc1 = (SiteNode) arg0;
186: SiteNode doc2 = (SiteNode) arg1;
187:
188: try {
189: if (AbstractSiteManager.this .requires(map, doc1,
190: doc2)) {
191: result = 1;
192: }
193: if (AbstractSiteManager.this .requires(map, doc2,
194: doc1)) {
195: result = -1;
196: }
197: } catch (SiteException e) {
198: throw new RuntimeException(e);
199: }
200: }
201: return result;
202: }
203: }
204:
205: }
|