Source Code Cross Referenced for RelationsManagerImpl.java in  » Content-Management-System » contelligent » de » finix » contelligent » core » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Content Management System » contelligent » de.finix.contelligent.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2001-2006 C:1 Financial Services GmbH
003:         *
004:         * This software is free software; you can redistribute it and/or
005:         * modify it under the terms of the GNU Lesser General Public
006:         * License Version 2.1, as published by the Free Software Foundation.
007:         *
008:         * This software is distributed in the hope that it will be useful,
009:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
010:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
011:         * Lesser General Public License for more details.
012:         *
013:         * You should have received a copy of the GNU Lesser General Public
014:         * License along with this library; if not, write to the Free Software
015:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
016:         */
017:
018:        package de.finix.contelligent.core;
019:
020:        import java.util.ArrayList;
021:        import java.util.HashSet;
022:        import java.util.Iterator;
023:        import java.util.LinkedList;
024:        import java.util.List;
025:        import java.util.Map;
026:        import java.util.Set;
027:        import java.util.Stack;
028:
029:        import de.finix.contelligent.CallData;
030:        import de.finix.contelligent.Component;
031:        import de.finix.contelligent.ComponentContext;
032:        import de.finix.contelligent.ComponentManager;
033:        import de.finix.contelligent.ComponentNotFoundException;
034:        import de.finix.contelligent.ComponentPath;
035:        import de.finix.contelligent.ComponentPathException;
036:        import de.finix.contelligent.Container;
037:        import de.finix.contelligent.ExternalRelationSource;
038:        import de.finix.contelligent.GlobalComponentPath;
039:        import de.finix.contelligent.ModificationVetoException;
040:        import de.finix.contelligent.RelationsManager;
041:        import de.finix.contelligent.category.CategoryException;
042:        import de.finix.contelligent.category.CategoryManager;
043:        import de.finix.contelligent.exception.ComponentPersistenceException;
044:        import de.finix.contelligent.exception.ContelligentException;
045:        import de.finix.contelligent.exception.ContelligentExceptionID;
046:        import de.finix.contelligent.logging.LoggingService;
047:        import de.finix.contelligent.persistence.ComponentPersistenceAdapter;
048:        import de.finix.contelligent.persistence.RelationsPersistenceAdapter;
049:        import de.finix.contelligent.render.Template;
050:        import de.finix.contelligent.resource.Resource;
051:        import de.finix.contelligent.resource.StringResource;
052:        import de.finix.contelligent.resource.TextResource;
053:
054:        public class RelationsManagerImpl implements  RelationsManager {
055:            final static org.apache.log4j.Logger log = LoggingService
056:                    .getLogger(RelationsManagerImpl.class);
057:
058:            final RelationsPersistenceAdapter relationsAdapter;
059:
060:            final CategoryManager categoryManager;
061:
062:            /**
063:             * Creates a new <code>RelationsManagerImpl</code> instance.
064:             */
065:            RelationsManagerImpl(RelationsPersistenceAdapter relationsAdapter,
066:                    CategoryManager categoryManager) {
067:                this .relationsAdapter = relationsAdapter;
068:                this .categoryManager = categoryManager;
069:            }
070:
071:            /**
072:             * Returns true if there are any relations in any manager to the given
073:             * target tree.
074:             * 
075:             * @param targetTree
076:             *            a <code>ComponentPath</code> value
077:             * @return a <code>boolean</code> value
078:             * @exception ComponentPersistenceException
079:             *                if an error occurs
080:             */
081:            public boolean existRelationsToTree(ComponentPath targetTree)
082:                    throws ComponentPersistenceException {
083:                return relationsAdapter.existRelationsToTree(targetTree);
084:            }
085:
086:            /**
087:             * Returns a <code>Map</code> containing (String,Set) entries mapping any
088:             * sub-path of the given target-tree where relations exist to a set of
089:             * <code>GlobalComponentPath</code> representing the source-paths of the
090:             * relations. Only relations from the given manager-id or higher manager are
091:             * considered. <BR>
092:             * Note that a {@link GlobalComponentPath} contains the id of the
093:             * ComponentManager where the associated component exists in and that a mere
094:             * ComponentPath never equals a GlobalComponentPath no matter whether the
095:             * paths are equal or not!
096:             * 
097:             * @param targetTree
098:             *            a <code>ComponentPath</code> value
099:             * @param includeSelf
100:             *            a <code>boolean</code> value
101:             * @param managerId
102:             *            only relations from components from this manager or higher
103:             *            managers are returned.
104:             * @return a <code>Map</code> of (String,Set) entries where each set
105:             *         contains <code>GlobalComponentPath</code> instances
106:             * @exception ComponentPersistenceException
107:             *                if an error occurs
108:             */
109:            public Map getGlobalPathsRelatedToTree(ComponentPath targetTree,
110:                    boolean includeSelf, long managerId)
111:                    throws ComponentPersistenceException {
112:                Map relations = relationsAdapter.getGlobalPathsRelatedToTree(
113:                        targetTree, includeSelf);
114:
115:                Iterator keys = relations.keySet().iterator();
116:                while (keys.hasNext()) {
117:                    ComponentPath targetPath = new ComponentPath((String) keys
118:                            .next());
119:                    if (!(targetPath.equals(targetTree) || targetPath
120:                            .isSubPathOf(targetTree))) {
121:                        // This filtering is necessary, because for performance reasons
122:                        // we do the actual database query through a LIKE and thus
123:                        // might get extra entries.
124:                        keys.remove();
125:                    }
126:                }
127:
128:                Iterator it = relations.values().iterator();
129:                while (it.hasNext()) {
130:                    Set relatedPaths = (Set) it.next();
131:                    Iterator relPaths = relatedPaths.iterator();
132:                    while (relPaths.hasNext()) {
133:                        GlobalComponentPath path = (GlobalComponentPath) relPaths
134:                                .next();
135:                        long pathCMId = path.getPersistenceManagerId();
136:                        // This makes sure Production moves are not blocked by
137:                        // changes in an edit context, by removing all paths
138:                        // that come from neither our context nor Production.
139:                        if ((pathCMId != managerId) && (pathCMId != -1)) {
140:                            relPaths.remove();
141:                        }
142:                    }
143:                    if (relatedPaths.isEmpty()) {
144:                        it.remove();
145:                    }
146:                }
147:                if (log.isDebugEnabled()) {
148:                    log.debug("getGlobalPathsRelatedToTree() - ending with "
149:                            + relations.size() + " map entries for tree '"
150:                            + targetTree + "'. (relations-map=" + relations
151:                            + ")");
152:                }
153:                return relations;
154:            }
155:
156:            /**
157:             * Same as {@link #getGlobalPathsRelatedToTree} but returns a set of
158:             * <code>ComponentPath</code> instances which is the union of all values
159:             * of the map where all <code>GlobalComponentPath</code> instances are
160:             * replaced by a ComponentPath.
161:             * 
162:             * @param targetTree
163:             *            a <code>ComponentPath</code> value
164:             * @param includeSelf
165:             *            a <code>boolean</code> value
166:             * @param managerId
167:             *            a <code>long</code> value
168:             * @return a <code>Set</code> value
169:             * @exception ComponentPersistenceException
170:             *                if an error occurs
171:             */
172:            public Set getPathsRelatedToTree(ComponentPath targetTree,
173:                    boolean includeSelf, long managerId)
174:                    throws ComponentPersistenceException {
175:                Map relationsMap = this .getGlobalPathsRelatedToTree(targetTree,
176:                        includeSelf, managerId);
177:                Set result = new HashSet();
178:                Iterator it = relationsMap.values().iterator();
179:                while (it.hasNext()) {
180:                    Set relatedPaths = (Set) it.next();
181:                    // we cannot make a real union because we have to replace global by
182:                    // normal componentpath !
183:                    // result.addAll((Set)it.next());
184:                    Iterator relPaths = relatedPaths.iterator();
185:                    while (relPaths.hasNext()) {
186:                        GlobalComponentPath path = (GlobalComponentPath) relPaths
187:                                .next();
188:                        result.add(new ComponentPath(path.toPath()));
189:                    }
190:                }
191:                if (log.isDebugEnabled()) {
192:                    log.debug("getPathsRelatedToTree() - ending with "
193:                            + result.size() + " relations to tree '"
194:                            + targetTree + "'. (relations=" + result + ")");
195:                }
196:                return result;
197:            }
198:
199:            /**
200:             * Returns a <code>Set</code> of <code>GlobalComponentPath</code>
201:             * instances each representing the path of a components which has a relation
202:             * to the given target path. Only relations from the given manager-id or
203:             * higher manager are considered.
204:             * 
205:             * @param target
206:             *            a <code>ComponentPath</code> value
207:             * @param managerId
208:             *            a <code>long</code> value
209:             * @return a <code>Set</code> value
210:             * @exception ComponentPersistenceException
211:             *                if an error occurs
212:             */
213:            public Set getGlobalPathsRelatedTo(ComponentPath target,
214:                    long managerId) throws ComponentPersistenceException {
215:                ContelligentImpl ci = ContelligentImpl.getInstance();
216:                String managerName = ci.getComponentManagerName(managerId);
217:                ComponentManager cm = ci.getComponentManager(managerName);
218:                Set relatedPaths = relationsAdapter
219:                        .getGlobalPathsRelatedTo(target);
220:                Iterator it = relatedPaths.iterator();
221:                while (it.hasNext()) {
222:                    GlobalComponentPath path = (GlobalComponentPath) it.next();
223:                    long pathCMId = path.getPersistenceManagerId();
224:                    if (!(pathCMId == managerId || pathCMId == ComponentPersistenceAdapter.ROOT_ID)) { // ignore
225:                        // any
226:                        // path
227:                        // which
228:                        // is
229:                        // not
230:                        // in
231:                        // the
232:                        // actual
233:                        // or
234:                        // root
235:                        // manager
236:                        it.remove();
237:                    } else if ((managerId != ComponentPersistenceAdapter.ROOT_ID)
238:                            && (pathCMId == ComponentPersistenceAdapter.ROOT_ID)) {
239:                        // check if source component was locally modified
240:                        if (cm.componentExists(path, false)) {
241:                            it.remove();
242:                        }
243:                    }
244:                }
245:                return relatedPaths;
246:            }
247:
248:            /**
249:             * retrieve all relations referenced from within a tree
250:             * 
251:             * @param source
252:             *            the trees root node
253:             * @param managerId
254:             *            the managerId to look into
255:             * @return a set of relations which are references in the source tree
256:             */
257:            public Set getTreeRelations(ComponentPath source, long managerId)
258:                    throws ComponentPersistenceException {
259:                Set relationPaths = relationsAdapter.getTreeRelations(source,
260:                        managerId);
261:                return relationPaths;
262:            }
263:
264:            public Set getTreeRelationSources(ComponentPath source,
265:                    long managerId) throws ComponentPersistenceException {
266:                Set relationPaths = relationsAdapter.getTreeRelationSources(
267:                        source, managerId);
268:                return relationPaths;
269:            }
270:
271:            void removeRelationsOfTree(ComponentPath sourceTree, long sourceCM)
272:                    throws ComponentPersistenceException {
273:                relationsAdapter.removeRelationsOfTree(sourceTree, sourceCM);
274:            }
275:
276:            void removeRelations(ComponentPath sourceTree, long sourceCM)
277:                    throws ComponentPersistenceException {
278:                relationsAdapter.removeRelations(sourceTree, sourceCM);
279:            }
280:
281:            public void moveRelationsOfTree(ComponentPath path,
282:                    long sourceManagerId, long targetManagerId,
283:                    boolean recursive) throws ComponentPersistenceException {
284:                relationsAdapter.moveRelationsOfTree(path, sourceManagerId,
285:                        targetManagerId, recursive);
286:            }
287:
288:            public Map getDeadRelations(ComponentPath path, long[] managerIds,
289:                    boolean completeSubtree)
290:                    throws ComponentPersistenceException {
291:                return relationsAdapter.getDeadRelations(path, managerIds,
292:                        completeSubtree);
293:            }
294:
295:            public void updateRelations(Component c, CallData callData,
296:                    boolean recursive) throws ComponentPersistenceException {
297:                ComponentManager manager = callData.getActualManager();
298:                Stack componentStack = new Stack();
299:                componentStack.push(c);
300:                while (!componentStack.empty()) {
301:                    Component component = (Component) componentStack.pop();
302:                    try {
303:                        ComponentContext ctx = component.getComponentContext();
304:                        Set relatedPaths = new HashSet(
305:                                extractRelatedPaths(component)); // extractRelatedPaths()
306:                        // returns
307:                        // a
308:                        // list
309:                        ComponentPath path = ctx.getPath();
310:                        long cmId = ctx.getPersistenceManager().getId();
311:                        if (log.isDebugEnabled()) {
312:                            log
313:                                    .debug("updateRelations() - updating relations of component '"
314:                                            + path
315:                                            + "' from manager "
316:                                            + cmId
317:                                            + " (relations="
318:                                            + relatedPaths
319:                                            + ") ...");
320:                        }
321:                        relationsAdapter.updateRelations(path, cmId,
322:                                relatedPaths);
323:
324:                        if (recursive && component instanceof  Container) {
325:                            Container container = (Container) component;
326:                            Iterator subNames = container
327:                                    .getSubcomponentNames();
328:                            while (subNames.hasNext()) {
329:                                String subComponentName = (String) subNames
330:                                        .next();
331:                                try {
332:                                    Component sub = manager.getSubcomponent(
333:                                            container, subComponentName,
334:                                            callData, false);
335:                                    // don't follow links
336:                                    componentStack.push(sub);
337:                                } catch (ComponentNotFoundException e) {
338:                                    log
339:                                            .error("updateRelations() - subcomponent '"
340:                                                    + subComponentName
341:                                                    + "' of container '"
342:                                                    + container
343:                                                    + "' not found although we used method 'getSubcomponentNames()' (skipping this tree): "
344:                                                    + e);
345:                                }
346:                            }
347:                        }
348:                    } catch (CategoryException e) {
349:                        log.error(
350:                                "updateRelations() - CategoryException while extracting relations of '"
351:                                        + component + "': ", e);
352:                        throw new ComponentPersistenceException(component
353:                                .getComponentContext().getPath(), e);
354:                    } catch (ComponentPersistenceException e) {
355:                        // Keep this from getting caught as ContelligentException
356:                        throw e;
357:                    } catch (ContelligentException e) {
358:                        log.error(
359:                                "updateRelations() - ContelligentException while extracting relations of '"
360:                                        + component + "': ", e);
361:                        throw new ComponentPersistenceException(component
362:                                .getComponentContext().getPath(), e);
363:                    }
364:                }
365:            }
366:
367:            /**
368:             * Updates all relations of the given component which would be affected by a
369:             * move of <tt>source</tt> to </tt>target</tt> before the move actually
370:             * happened.
371:             * 
372:             * @param component
373:             *            the component to change relations of.
374:             * @param source
375:             *            the source of the move.
376:             * @param target
377:             *            the target of the move.
378:             * @exception ComponentPersistenceException
379:             *                if an error occurs
380:             * @exception ModificationVetoException
381:             *                if an error occurs
382:             * @exception ComponentPathException
383:             *                if an error occurs
384:             */
385:            public void updateRelationsForMove(Component component,
386:                    ComponentPath source, ComponentPath target)
387:                    throws ComponentPersistenceException,
388:                    ModificationVetoException, ContelligentException {
389:                final boolean debugEnabled = log.isDebugEnabled();
390:                if (debugEnabled)
391:                    log.debug("updateRelationsForMove() - checking component '"
392:                            + component + "' ...");
393:
394:                long currentTime = TimeService.getInstance()
395:                        .currentTimeMillis();
396:                ComponentContext ctx = component.getComponentContext();
397:                ComponentPath componentPath = ctx.getPath();
398:                ComponentPath effectivePath = null;
399:                if (debugEnabled)
400:                    log.debug("updateRelationsForMove() - comparing path '"
401:                            + componentPath + "' and '" + source + "' ...");
402:
403:                // Note that "effectivePath" means "new location of componentPath",
404:                // which is the root path used for relative references. "componentPath"
405:                // is the root path of the reference before the move takes place.
406:
407:                if (source.equals(componentPath)) {
408:                    effectivePath = target;
409:                } else if (componentPath.isSubPathOf(source)) {
410:                    effectivePath = componentPath
411:                            .exchangeParent(source, target);
412:                } else {
413:                    effectivePath = componentPath;
414:                }
415:                if (debugEnabled)
416:                    log.debug("updateRelationsForMove() - EXCHANGE: path='"
417:                            + componentPath + "', effective='" + effectivePath
418:                            + "' ...");
419:
420:                if (component instanceof  ExternalRelationSource) {
421:                    ExternalRelationSource externalRelationSource = (ExternalRelationSource) component;
422:                    List relatedPaths = externalRelationSource.relatedPaths();
423:                    ArrayList newRelatedPaths = new ArrayList(relatedPaths
424:                            .size());
425:                    Iterator paths = relatedPaths.iterator();
426:                    while (paths.hasNext()) {
427:                        ComponentPath path = (ComponentPath) paths.next();
428:                        ComponentPath replacedPath = replacePath(path, source,
429:                                target, ctx.getPath(), effectivePath);
430:                        if (replacedPath != null) {
431:                            if (debugEnabled) {
432:                                log
433:                                        .debug("updateRelationsForMove() - replaced path '"
434:                                                + path
435:                                                + "' of component '"
436:                                                + component
437:                                                + "' with '"
438:                                                + replacedPath
439:                                                + "' (while moving '"
440:                                                + source
441:                                                + "' to '" + target + "')");
442:                            }
443:                            newRelatedPaths.add(replacedPath);
444:                        } else {
445:                            if (debugEnabled) {
446:                                log.debug("updateRelationsForMove() - path '"
447:                                        + path + "' of component '" + component
448:                                        + "' not replaced (while moving '"
449:                                        + source + "' to '" + target + "')");
450:                            }
451:                            newRelatedPaths.add(path);
452:                        }
453:                    }
454:                    externalRelationSource.relatedPaths(newRelatedPaths); // throws
455:                    // ModificationVetoException;
456:                } else {
457:                    // the template-resources:
458:                    Iterator it = ctx.getTemplateResourceIdentifiers()
459:                            .iterator();
460:                    while (it.hasNext()) {
461:                        int replaced = 0;
462:                        String identifier = (String) it.next();
463:                        Resource resource = (Resource) ctx
464:                                .getTemplateResource(identifier);
465:                        if (resource.isBinary() || resource.isNumber()) {
466:                            if (debugEnabled) {
467:                                log
468:                                        .debug("updateRelationsForMove() - ignoring binary|number resource '"
469:                                                + identifier
470:                                                + "' of component '"
471:                                                + component + "' ...");
472:                            }
473:                        } else if (resource.isText()) {
474:                            StringBuffer text = new StringBuffer(
475:                                    ((TextResource) resource).getString());
476:                            replaced = updateContents(source, target, text, ctx
477:                                    .getPath(), effectivePath);
478:                            if (replaced > 0) {
479:                                resource = new TextResource(text.toString(),
480:                                        currentTime);
481:                            }
482:                        } else if (resource.isString()) {
483:                            StringBuffer text = new StringBuffer(
484:                                    ((StringResource) resource).getString());
485:                            replaced = updateContents(source, target, text, ctx
486:                                    .getPath(), effectivePath);
487:                            if (replaced > 0) {
488:                                resource = new StringResource(text.toString(),
489:                                        currentTime);
490:                            }
491:                        } else { // The resource type is unknown.
492:                            log.error("updateRelationsForMove() - resource '"
493:                                    + identifier + "' of component '"
494:                                    + component
495:                                    + "' has unknown resource type (ignored).");
496:                        }
497:                        if (replaced > 0) {
498:                            ctx.setTemplateResource(identifier, resource);
499:                        }
500:                    }
501:
502:                    // now the content-resources:
503:                    it = ctx.getContentResourceIdentifiers().iterator();
504:                    while (it.hasNext()) {
505:                        int replaced = 0;
506:                        String identifier = (String) it.next();
507:                        Resource resource = (Resource) ctx
508:                                .getContentResource(identifier);
509:                        if (resource.isBinary() || resource.isNumber()) {
510:                            if (debugEnabled) {
511:                                log
512:                                        .debug("updateRelationsForMove() - ignoring binary|number resource '"
513:                                                + identifier
514:                                                + "' of component '"
515:                                                + component + "' ...");
516:                            }
517:                        } else if (resource.isText()) {
518:                            StringBuffer text = new StringBuffer(
519:                                    ((TextResource) resource).getString());
520:                            replaced = updateContents(source, target, text, ctx
521:                                    .getPath(), effectivePath);
522:                            if (replaced > 0) {
523:                                resource = new TextResource(text.toString(),
524:                                        currentTime);
525:                            }
526:                        } else if (resource.isString()) {
527:                            StringBuffer text = new StringBuffer(
528:                                    ((StringResource) resource).getString());
529:                            replaced = updateContents(source, target, text, ctx
530:                                    .getPath(), effectivePath);
531:                            if (replaced > 0) {
532:                                resource = new StringResource(text.toString(),
533:                                        currentTime);
534:                            }
535:                        } else {
536:                            log.error("updateRelationsForMove() - resource '"
537:                                    + identifier + "' of component '"
538:                                    + component
539:                                    + "' has unknown resource type (ignored).");
540:                        }
541:                        if (replaced > 0) {
542:                            ctx.setContentResource(identifier, resource);
543:                        }
544:                    }
545:                }
546:            }
547:
548:            /**
549:             * Extracts the relations of the given component. Any resource associated
550:             * with the component except {@link Resource#isBinary binary}
551:             * {@link Resource#isNumber number} resources are automatically scanned for
552:             * related paths. If the component implements {@link ExternalRelationSource}
553:             * the component itself is asked instead.
554:             * 
555:             * @return a <code>List</code> containing <code>ComponentPath</code>
556:             *         instances where every path represents a relation of the
557:             *         component. All paths are absolute and any category-token gets
558:             *         replaced by its default value.
559:             */
560:            public List extractRelatedPaths(Component component)
561:                    throws ComponentPersistenceException, CategoryException,
562:                    ContelligentException {
563:                final boolean debugEnabled = log.isDebugEnabled();
564:                if (debugEnabled)
565:                    log.debug("extractRelatedPaths() - checking component '"
566:                            + component + "' ...");
567:
568:                ComponentContext ctx = component.getComponentContext();
569:                List relatedPathSet = new LinkedList();
570:
571:                if (component instanceof  ExternalRelationSource) {
572:                    ExternalRelationSource externalRelationSource = (ExternalRelationSource) component;
573:                    List relatedPaths = externalRelationSource.relatedPaths();
574:                    relatedPathSet.addAll(relatedPaths);
575:                    if (debugEnabled) {
576:                        log
577:                                .debug("extractRelatedPaths() - done with ExternalRelationSource '"
578:                                        + component + "'.");
579:                    }
580:                } else {
581:                    Set templateResources = ctx
582:                            .getTemplateResourceIdentifiers();
583:                    Set contentResources = ctx.getContentResourceIdentifiers();
584:                    if (debugEnabled) {
585:                        log.debug("extractRelatedPaths() - component '"
586:                                + component + "' has "
587:                                + templateResources.size() + " template- and "
588:                                + contentResources.size()
589:                                + " content-resource.");
590:                    }
591:                    Resource[] resources = new Resource[templateResources
592:                            .size()
593:                            + contentResources.size()];
594:                    int i = 0;
595:                    Iterator it = templateResources.iterator();
596:                    while (it.hasNext()) {
597:                        String identifier = (String) it.next();
598:                        resources[i++] = ctx.getTemplateResource(identifier);
599:                    }
600:                    it = contentResources.iterator();
601:                    while (it.hasNext()) {
602:                        String identifier = (String) it.next();
603:                        resources[i++] = ctx.getContentResource(identifier);
604:                    }
605:
606:                    for (i = 0; i < resources.length; i++) {
607:                        Resource resource = resources[i];
608:                        if (resource.isBinary() || resource.isNumber()) {
609:                            if (debugEnabled) {
610:                                log
611:                                        .debug("extractRelatedPaths() - ignoring binary|number resource of component '"
612:                                                + component + "' ...");
613:                            }
614:                        } else if (resource.isString() || resource.isText()) {
615:                            String resContent = ((StringResource) resource)
616:                                    .getString();
617:                            if (resContent != null && resContent.length() > 0) {
618:                                Template template = new Template(resContent); // throws
619:                                // ContelligentException
620:                                relatedPathSet.addAll(template
621:                                        .getPathsOfRelationTargets());
622:                            } else {
623:                                if (debugEnabled)
624:                                    log
625:                                            .debug("extractRelatedPaths() - ignoring empty resource of component '"
626:                                                    + component + "' ...");
627:                            }
628:                        } else {
629:                            // The resource type is unknown.
630:                            log
631:                                    .error("extractRelatedPaths() - a resource of component '"
632:                                            + component
633:                                            + "' has an unknown resource-type (ignored).");
634:                        }
635:                    }
636:                }
637:
638:                List result = new LinkedList();
639:                // handling of categories and relative paths:
640:                Iterator relatedPaths = relatedPathSet.iterator();
641:                while (relatedPaths.hasNext()) {
642:                    ComponentPath path = (ComponentPath) relatedPaths.next();
643:                    // XXX: this is a hack to prevent tags with dynamicly created path
644:                    // attributes for example
645:                    // in XSL templates to be added as a relation. (20030131, rs)
646:                    if (path.toString().indexOf("{") != -1) {
647:                        if (debugEnabled)
648:                            log
649:                                    .debug("extractRelatedPaths() - ignoring relation '"
650:                                            + path + "' (dynamic XSL?) ...");
651:                        relatedPaths.remove();
652:                        continue;
653:                    }
654:                    if (categoryManager.containsCategory(path)) {
655:                        ComponentPath oldPath = path;
656:                        path = categoryManager.expandCategories(path,
657:                                categoryManager.getDefaultCategoryMap());
658:                        if (debugEnabled)
659:                            log
660:                                    .debug("extractRelatedPaths() - expanded categories in path '"
661:                                            + oldPath
662:                                            + "' to '"
663:                                            + path
664:                                            + "' ...");
665:                    }
666:                    if (path.isRelative()) {
667:                        path = path.toAbsolutePath(ctx.getPath());
668:                    }
669:
670:                    result.add(path);
671:                }
672:                return result;
673:            }
674:
675:            /**
676:             * Replaces all paths in the given <tt>contents</tt> which are affected by
677:             * moving <tt>oldPath</tt> to <tt>newPath</tt>. <BR>
678:             * Note that the given component is expected to rely in the <b>target tree</b>
679:             * which is important when relative paths must be changed.
680:             * 
681:             * @param oldPath
682:             *            The source path of the move operation.
683:             * @param newPath
684:             *            The target path of the move operation.
685:             * @param contents
686:             *            The content whose contained references are to be updated.
687:             * @param oldRootPath
688:             *            Location of the component holding the reference as before the
689:             *            move.
690:             * @param newRootPath
691:             *            Location of the component holding the reference as after the
692:             *            move. If oldRootPath is not a subpath of oldPath, this must be
693:             *            the same as oldRootPath.
694:             * @return an <code>int</code> value
695:             * @exception ComponentPathException
696:             *                if an error occurs
697:             */
698:            private int updateContents(ComponentPath oldPath,
699:                    ComponentPath newPath, StringBuffer contents,
700:                    ComponentPath oldRootPath, ComponentPath newRootPath)
701:                    throws ContelligentException {
702:                final boolean debugEnabled = log.isDebugEnabled();
703:
704:                final String TAG_TOSEARCH = Template.FINIX_TAG_PREFIX
705:                        + Template.RENDER_IDENTIFIER;
706:                final int TAG_TOSEARCH_LENGTH = TAG_TOSEARCH.length();
707:
708:                if (debugEnabled)
709:                    log
710:                            .debug("updateContents() - searching related paths in contents ["
711:                                    + contents + "] ...");
712:
713:                int replaced = 0;
714:                int pos = 0;
715:                while (pos < contents.length()) {
716:                    int i = contents.substring(pos).indexOf(TAG_TOSEARCH);
717:                    if (i == -1)
718:                        break;
719:
720:                    if (debugEnabled)
721:                        log.debug("updateContents() - found tag '"
722:                                + TAG_TOSEARCH + "' at position " + i + " ...");
723:
724:                    pos += (i + TAG_TOSEARCH_LENGTH);
725:
726:                    while (pos < contents.length()
727:                            && Character.isWhitespace(contents.charAt(pos)))
728:                        ++pos; // skip whitespaces
729:
730:                    if (!(contents.substring(pos, pos
731:                            + Template.PATH_ATTRIBUTE.length())
732:                            .equals(Template.PATH_ATTRIBUTE))) {
733:                        log.error("updateContents() - attribute '"
734:                                + Template.PATH_ATTRIBUTE
735:                                + "' is missing at position " + pos
736:                                + " in tag " + TAG_TOSEARCH + " in contents ["
737:                                + contents + "]!");
738:                        throw new ContelligentException(
739:                                ContelligentExceptionID.component_invalidRenderTag);
740:                    }
741:                    pos += Template.PATH_ATTRIBUTE.length(); // add length of path
742:                    // attribute
743:                    while (pos < contents.length()
744:                            && Character.isWhitespace(contents.charAt(pos)))
745:                        ++pos; // skip whitespaces
746:
747:                    if (contents.charAt(pos++) != '=') {
748:                        log.error("updateContents() - attribute '"
749:                                + Template.PATH_ATTRIBUTE
750:                                + "' must be followed by '='!");
751:                        throw new ContelligentException(
752:                                ContelligentExceptionID.component_invalidRenderTag);
753:                    }
754:                    while (pos < contents.length()
755:                            && Character.isWhitespace(contents.charAt(pos)))
756:                        ++pos; // skip whitespaces
757:
758:                    // we allow both ' and "
759:                    i = -1;
760:                    if (contents.charAt(pos) == '"') {
761:                        i = contents.substring(++pos).indexOf('"');
762:                    } else if (contents.charAt(pos) == '\'') {
763:                        i = contents.substring(++pos).indexOf('\'');
764:                    }
765:                    if (i == -1) {
766:                        log
767:                                .error("updateContents() - value of attribute '"
768:                                        + Template.PATH_ATTRIBUTE
769:                                        + "' must be included in quotes [\" or '] (in component '"
770:                                        + oldRootPath + "')");
771:                        throw new ContelligentException(
772:                                ContelligentExceptionID.component_invalidRenderTag);
773:                    }
774:
775:                    String s = contents.substring(pos, pos + i);
776:                    int questionMark = s.indexOf('?');
777:                    ComponentPath pathToReplace = (questionMark == -1) ? new ComponentPath(
778:                            s)
779:                            : new ComponentPath(s.substring(0, questionMark));
780:                    ComponentPath replacedPath = replacePath(pathToReplace,
781:                            oldPath, newPath, oldRootPath, newRootPath);
782:                    if (replacedPath != null) {
783:                        if (questionMark == -1) {
784:                            contents.replace(pos, pos + i, replacedPath
785:                                    .toString());
786:                        } else {
787:                            contents.replace(pos, pos + questionMark,
788:                                    replacedPath.toString());
789:                        }
790:                        pos += replacedPath.toString().length() + 1;
791:                        replaced++;
792:                    } else {
793:                        pos += (i + 1);
794:                    }
795:                }
796:
797:                if (debugEnabled)
798:                    log.debug("updateContents() - replaced " + replaced
799:                            + " paths in contents [" + contents + "] ...");
800:                return replaced;
801:            }
802:
803:            /**
804:             * Checks the specified pathFromTag which is expected to originate from the
805:             * given component's content whether it must be changed when moving a
806:             * component tree from oldPath to newPath. <BR>
807:             * Returns null if the given path is not affected by the move or else the
808:             * modified path.
809:             * 
810:             * @param pathFromTag
811:             *            The path (relative or absolute) as stored in the reference to
812:             *            be changed.
813:             * @param oldPath
814:             *            The source path of the move operation.
815:             * @param newPath
816:             *            The target path of the move operation.
817:             * @param oldRootPath
818:             *            Location of the component holding the reference as before the
819:             *            move.
820:             * @param newRootPath
821:             *            Location of the component holding the reference as after the
822:             *            move. If oldRootPath is not either a subpath of oldPath or
823:             *            equal to oldPath, this must be the same as oldRootPath,
824:             *            otherwise it must be a subpath of or equal to newPath.
825:             * @return a new relative or absolute path or null if the path needs no
826:             *         modification
827:             * @exception ComponentPathException
828:             *                if an error occurs
829:             */
830:            final private ComponentPath replacePath(ComponentPath pathFromTag,
831:                    ComponentPath oldPath, ComponentPath newPath,
832:                    ComponentPath oldRootPath, ComponentPath newRootPath)
833:                    throws ComponentPathException {
834:                ComponentPath path = (pathFromTag.isAbsolute() ? pathFromTag
835:                        : pathFromTag.toAbsolutePath(oldRootPath));
836:
837:                // Some parameter contract checks coming up
838:                if (!oldPath.isAbsolute()) {
839:                    throw new IllegalArgumentException("oldPath " + oldPath
840:                            + " is not an absolute path.");
841:                }
842:
843:                if (!newPath.isAbsolute()) {
844:                    throw new IllegalArgumentException("newPath " + newPath
845:                            + " is not an absolute path.");
846:                }
847:
848:                if (!oldRootPath.isAbsolute()) {
849:                    throw new IllegalArgumentException("oldRootPath "
850:                            + oldRootPath + " is not an absolute path.");
851:                }
852:
853:                if (!newRootPath.isAbsolute()) {
854:                    throw new IllegalArgumentException("newRootPath "
855:                            + newRootPath + " is not an absolute path.");
856:                }
857:
858:                if ((!(oldRootPath.isSubPathOf(oldPath) || oldRootPath
859:                        .equals(oldPath)))
860:                        && (!oldRootPath.equals(newRootPath))) {
861:                    throw new IllegalArgumentException(
862:                            "oldRootPath "
863:                                    + oldRootPath
864:                                    + " is outside the tree to be moved but still has a different newRootPath.");
865:                }
866:
867:                if ((oldRootPath.isSubPathOf(oldPath) || oldRootPath
868:                        .equals(oldPath))
869:                        && (!(newRootPath.isSubPathOf(newPath) || newRootPath
870:                                .equals(newPath)))) {
871:                    throw new IllegalArgumentException(
872:                            "oldRootPath "
873:                                    + newRootPath
874:                                    + " is inside the tree to be moved but newRootPath does not fall within the move destination.");
875:                }
876:
877:                // We might have to make an adjustment to the reference if it is either
878:                // targetting a location within the tree to be moved OR is both
879:                // sourced within the tree to be moved and relative (in the latter
880:                // case it is the .. paths pointing to outside the tree that we are
881:                // concerned about)
882:                if (path.equals(oldPath)
883:                        || path.isSubPathOf(oldPath)
884:                        || ((oldRootPath.equals(oldPath) || oldRootPath
885:                                .isSubPathOf(oldPath)) && pathFromTag
886:                                .isRelative())) {
887:
888:                    // Prefill result in case the reference target is not being moved
889:                    ComponentPath result = path;
890:
891:                    // If the target is being moved, adjust it
892:                    if (path.equals(oldPath) || path.isSubPathOf(oldPath)) {
893:                        result = path.equals(oldPath) ? newPath : path
894:                                .exchangeParent(oldPath, newPath);
895:                    }
896:
897:                    // At this point, the result variable contains the absolute path of
898:                    // the reference target as it will be after the move
899:
900:                    // Convert the result to a relative path, if appropriate
901:                    // TODO: Think about whether always keeping relative paths relative
902:                    // is
903:                    // the right way to go; this should be the only place the code needs
904:                    // to be touched to change this at the time of writing.
905:                    if (pathFromTag.isRelative()) {
906:                        result = result.toRelativePath(newRootPath);
907:                    }
908:                    if (log.isDebugEnabled()) {
909:                        log
910:                                .debug("replacePath() - replaced path in component '"
911:                                        + oldRootPath
912:                                        + "' ('"
913:                                        + pathFromTag
914:                                        + "' => '"
915:                                        + result
916:                                        + "' while moving '"
917:                                        + oldPath
918:                                        + "' => '" + newPath + "')");
919:                    }
920:                    return result;
921:                } else {
922:                    if (log.isDebugEnabled()) {
923:                        log.debug("replacePath() - path '" + pathFromTag
924:                                + "' in component '" + oldRootPath
925:                                + "' must not be changed. (while moving '"
926:                                + oldPath + "' => '" + newPath + "')");
927:                    }
928:                    return null; // null indicates the path has not to be changed!
929:                }
930:            }
931:
932:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.