View Javadoc

1   package org.astrogrid.portal.transformation;
2   
3   import java.io.File;
4   import java.io.FilenameFilter;
5   import java.io.IOException;
6   import java.net.MalformedURLException;
7   import java.net.URI;
8   import java.net.URL;
9   import java.util.Map;
10  import java.util.regex.Pattern;
11  
12  import org.apache.avalon.framework.logger.Logger;
13  import org.apache.avalon.framework.parameters.Parameters;
14  import org.apache.cocoon.ProcessingException;
15  import org.apache.cocoon.environment.SourceResolver;
16  import org.apache.cocoon.transformation.AbstractDOMTransformer;
17  import org.apache.commons.jxpath.JXPathContext;
18  import org.apache.commons.jxpath.xml.DocumentContainer;
19  import org.apache.excalibur.source.Source;
20  import org.w3c.dom.Document;
21  import org.w3c.dom.Element;
22  import org.xml.sax.SAXException;
23  
24  /***
25   * Add the non-specified menus to the main menu.
26   */
27  public class MenuTransformer extends AbstractDOMTransformer {
28    private String menuDirectory = null;
29    private String menuHref = null;
30  
31    /* (non-Javadoc)
32     * @see org.apache.cocoon.sitemap.SitemapModelComponent#setup(org.apache.cocoon.environment.SourceResolver, java.util.Map, java.lang.String, org.apache.avalon.framework.parameters.Parameters)
33     */
34    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters params)
35        throws ProcessingException, SAXException, IOException {
36      super.setup(resolver, objectModel, src, params);
37      
38      Logger logger = this.getLogger();
39      logger.info("[setup]");
40  
41      menuDirectory = resolveMenuDirectory(resolver, params);
42      
43      logger.info("[setup] menu href: " + menuHref);
44    }
45  
46    /* (non-Javadoc)
47     * @see org.apache.cocoon.transformation.AbstractDOMTransformer#transform(org.w3c.dom.Document)
48     */
49    protected Document transform(Document doc) {
50      Document result = doc;
51      
52      Logger logger = this.getLogger();
53  
54  /*
55      Element menuEl =
56        result.createElementNS("http://www.astrogrid.org/portal", "menu");
57      menuEl.setAttribute("display", "Miscellaneous");
58      menuEl.setAttribute("name", "MenuTransformer");
59  */
60      logger.info("[transform] create menu element");
61  
62  //    Element menuLinkEl =
63  //      result.createElementNS("http://www.astrogrid.org/portal", "link");
64  //    Node linkText = result.createTextNode("http://www.astrogrid.org");
65  //    menuLinkEl.appendChild(linkText);
66  //    menuEl.appendChild(menuLinkEl);
67  
68      logger.info("[transform] created menu link element");
69  
70      Element rootMenuEl = (Element) result.getFirstChild();
71  //    rootMenuEl.appendChild(menuEl);
72  
73      logger.info("[transform] added new menu to main menu");
74  
75      result = addMenus(result, rootMenuEl, doc);
76      
77      logger.info("[transform] added sub menus");
78  
79      return result;
80    }
81  
82    private Document addMenus(Document doc, Element menuEl, Document sourceDoc) {
83      Document result = doc;
84  
85      Logger logger = this.getLogger();
86  
87      File menuFile = null;
88      Element xIncludeEl = null;
89      File[] menuFiles = null;
90      
91      try {
92        menuFiles = listMenuFiles(menuDirectory);
93      }
94      catch(Throwable t) {
95        // Do nothing.
96      }
97      
98      logger.info("[addMenus] menu files: " + menuFiles);
99      
100     if(menuFiles != null) {
101       for (int fileIndex = 0; fileIndex < menuFiles.length; fileIndex++) {
102         menuFile = menuFiles[fileIndex];
103   
104         xIncludeEl =
105           result.createElementNS("http://www.w3.org/2001/XInclude", "xi:include");
106         xIncludeEl.setAttribute("href", menuDirectory + menuFile.getName());
107   
108         if(testMenuInclude(sourceDoc.getDocumentElement(), menuFile)) {
109           menuEl.appendChild(xIncludeEl);
110         }
111       }
112     }
113     else {
114       logger.debug("[addMenus] no files... directory: " + menuDirectory);
115     }
116 
117     return result;
118   }
119 
120   private File[] listMenuFiles(String menuDirectory) throws Throwable {
121     final Logger logger = this.getLogger();
122 
123     try {
124       File menuDirectoryFile = new File(menuDirectory);
125 
126      return menuDirectoryFile.listFiles(new FilenameFilter() {
127         public boolean accept(File dir, String name) {
128           logger.info("[FilenameFilter.accept] dir: " + dir + ", name: " + name);
129           if (name.equals("menu.xml")) {
130             return false;
131           }
132   
133           return Pattern.matches(".*//.xml", name);
134         }
135       });
136     }
137     catch(Throwable t) {
138       logger.debug("[listMenuFiles]", t);
139       throw t;
140     }
141   }
142 
143   private boolean testMenuInclude(Element menu, File toInclude) {
144     boolean result = false;
145     
146     try {
147       URL includeUrl = toInclude.toURL();
148             
149       JXPathContext menuContext = JXPathContext.newContext(menu);
150       JXPathContext fileContext = JXPathContext.newContext(new DocumentContainer(includeUrl));
151       
152       String fileMenuName = (String) fileContext.getValue("/agp:menu-def/@name");
153       Double menuValue = (Double) menuContext.getValue("count(//agp:menu-def[@name='" + fileMenuName + "'])");
154       
155       result = (menuValue.doubleValue() == 0.0d);
156     }
157     catch(MalformedURLException e) {
158       result = false;
159     }
160     
161     return result;
162   }
163   
164   private String resolveMenuDirectory(SourceResolver resolver, Parameters params)
165     throws MalformedURLException, IOException {
166     String menuDirectoryParam = params.getParameter("menu-directory", "");
167     Source menuDirectorySource = resolver.resolveURI(menuDirectoryParam);
168     String menuDirectoryURI = menuDirectorySource.getURI(); 
169     URI uri = URI.create(menuDirectoryURI);
170     
171     return uri.getPath();
172   }
173 }