svn commit: r693670 [4/6] - in /lenya/branches/revolution/1.3.x: ./ src/java/org/apache/lenya/cms/ac/ src/java/org/apache/lenya/cms/ac/usecase/ src/java/org/apache/lenya/cms/ac/workflow/ src/java/org/apache/lenya/cms/ant/ src/java/org/apache/lenya/cms/...

[email protected]
Newsgroups gmane.comp.cms.lenya.cvs
Message-ID <[email protected]>
Modified: lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/CreateRevisionTransformer.java
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/CreateRevisionTransformer.java?rev=693670&r1=693669&r2=693670&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/CreateRevisionTransformer.java (original)
+++ lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/CreateRevisionTransformer.java Tue Sep  9 17:30:20 2008
@@ -5,12 +5,18 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.cocoon.environment.ObjectModelHelper;
 import org.apache.cocoon.environment.Request;
 import org.apache.cocoon.servlet.multipart.Part;
 import org.apache.cocoon.transformation.AbstractDOMTransformer;
 import org.apache.lenya.cms.content.Content;
+import org.apache.lenya.cms.content.Location;
+import org.apache.lenya.cms.content.ResourceTransformer;
 import org.apache.lenya.cms.publication.PageEnvelope;
+import org.apache.lenya.cms.publication.PageEnvelopeException;
 import org.apache.lenya.cms.publication.Publication;
 import org.apache.lenya.util.Globals;
 import org.apache.lenya.xml.DocumentHelper;
@@ -22,21 +28,26 @@
  * @author solprovider
  * @since 1.3
  */
-public class CreateRevisionTransformer extends AbstractDOMTransformer {
-   public static final String UPLOADASSET_PARAM_PREFIX = "dc.";
-   public static final String UPLOADASSET_RETURN_FILESIZE = "file-size";
-   public static final String UPLOADASSET_RETURN_MIMETYPE = "mime-type";
-   public static final String CONTENT_PREFIX = "content";
-   public static final String FILE_NAME_REGEXP = "[-a-zA-Z0-9_. ]+";
+public class CreateRevisionTransformer extends AbstractDOMTransformer implements Configurable {
+   private static final String UPLOADASSET_PARAM_PREFIX = "dc.";
+   // private static final String UPLOADASSET_RETURN_FILESIZE = "file-size";
+   // private static final String UPLOADASSET_RETURN_MIMETYPE = "mime-type";
+   // private static final String CONTENT_PREFIX = "content";
+   // private static final String FILE_NAME_REGEXP = "[-a-zA-Z0-9_. ]+";
    // optional parameters for meta data according to dublin core
-   public static final String[] DUBLIN_CORE_PARAMETERS = {"title", "creator", "subject", "description", "publisher", "contributor", "date", "type", "format", "identifier", "source", "language", "relation", "coverage", "rights"};
+   private static final String[] DUBLIN_CORE_PARAMETERS = {"title", "creator", "subject", "description", "publisher", "contributor", "date", "type", "format", "identifier", "source", "language", "relation", "coverage", "rights"};
+   private String type = ResourceTransformer.TYPE_CONTENT;
+   public void configure(Configuration conf) throws ConfigurationException {
+      Configuration child = conf.getChild("type");
+      type = child.getValue(type);
+   }
    protected org.w3c.dom.Document transform(org.w3c.dom.Document doc) {
       Request request = ObjectModelHelper.getRequest(super.objectModel);
-      createRevision(request, this.source, doc, false);
+      createRevision(request, this.source, doc, type, false);
       return doc;
    }
-   static public org.w3c.dom.Document transformDocument(Request request, String unid, org.w3c.dom.Document doc, boolean setLive) {
-      createRevision(request, unid, doc, setLive);
+   static public org.w3c.dom.Document transformDocument(Request request, String unid, org.w3c.dom.Document doc, String type, boolean setLive) {
+      createRevision(request, unid, doc, type, setLive);
       return doc;
    }
    /**
@@ -45,25 +56,50 @@
     * @param doc
     *           The data to be inserted.
     */
-   static private void createRevision(Request request, String unid, org.w3c.dom.Document doc, boolean setLive) {
+   static private void createRevision(Request request, String unid, org.w3c.dom.Document doc, String type, boolean setLive) {
+      System.out.println("CreateRevisionTransformer createRevision TYPE=" + type);
       if(doc == null){
          System.out.println("CreateRevision: Document is required.");
          // throw new ProcessingException("CreateRevision: document is required.");
       }
-      PageEnvelope envelope = (PageEnvelope) request.getAttribute(PageEnvelope.class.getName());
-      Publication pub = envelope.getPublication();
+      Publication pub = Globals.getPublication();
       Content content = pub.getContent();
-      String workUnid = unid;
-      String language = envelope.getDocument().getLanguage(); // default
-      // check if unid contains language
-      int pos = workUnid.indexOf("_");
-      if(pos > 0){ // Use unid to avoid using the variable that is changing.
-         language = unid.substring(pos + 1);
-         workUnid = unid.substring(0, pos);
-      }
+      FlatDesign design = pub.getDesign();
+      Location location = new Location(unid);
+      String workUnid = location.getUnid();
+      String language = location.getLanguage();
       // System.out.println("CreateRevision TEST: u=" + unid + " w=" + workUnid + " l=" + language + " p=" + pos);
-      String newFilename = content.getNewURI(workUnid, language);
-      if(newFilename == null){
+      String newFilename;
+      if(ResourceTransformer.TYPE_DESIGN.equalsIgnoreCase(type)){
+         if(null == design){
+            System.out.println("CreateRevision Design: No Design.");
+            return;
+            // TODO: Throw exception.
+         }else{
+            language = FlatDesign.DESIGN_LANGUAGE;
+            newFilename = design.getDesign(workUnid).getNewURI();
+         }
+      }else if(ResourceTransformer.TYPE_STRUCTURE.equalsIgnoreCase(type)){
+         if(null == design){
+            System.out.println("CreateRevision Structure: No Design.");
+            return;
+            // TODO: Throw exception.
+         }else{
+            language = FlatDesign.DESIGN_LANGUAGE;
+            newFilename = design.getStructure(workUnid).getNewURI();
+            System.out.println("CreateRevision Structure filename=" + newFilename);
+         }
+      }else{ // TYPE_CONTENT
+         if(1 > language.length()){
+            try{
+               language = PageEnvelope.getCurrent().getDocument().getLanguage();
+            }catch(PageEnvelopeException e1){
+            }
+         }
+         if(1 > language.length()) language = pub.getDefaultLanguage();
+         newFilename = content.getNewURI(workUnid, language);
+      }
+      if(null == newFilename){
          System.out.println("CreateRevision: Could not get new filename.");
          // throw new ProcessingException("CreateRevision: Could not get new filename.");
       }
@@ -73,24 +109,21 @@
          // throw new ProcessingException("Revision '" + newFilename + "' already exists.");
       }
       String filenameNoExtension = newFilename;
-      pos = newFilename.lastIndexOf(".");
-      if(pos > 0)
-         filenameNoExtension = newFilename.substring(0, pos);
+      int pos = newFilename.lastIndexOf(".");
+      if(pos > 0) filenameNoExtension = newFilename.substring(0, pos);
       String revision = (new File(filenameNoExtension)).getName();
       File assetFile;
-      // determine if the upload is an asset or a content upload
+      // Determine if the upload is an asset or a content upload
       Map dublinCoreParams = getDublinCoreParameters(request);
-      // upload the file to the uploadDir
+      // Upload the file to the uploadDir
       String extension = "";
-      // Document metadoc = (Document) null;
       Element root = doc.getDocumentElement();
       if(root.hasAttribute("filefield")){
          Part part = (Part) request.get(root.getAttribute("filefield"));
          if(null != part){
             String filename = part.getFileName();
             pos = filename.lastIndexOf(".");
-            if(pos > 0)
-               extension = filename.substring(pos + 1);
+            if(pos > 0) extension = filename.substring(pos + 1);
             // System.out.println("Upload: EXT=" + extension);
             String mimeType = part.getMimeType();
             dublinCoreParams.put("format", mimeType);
@@ -111,8 +144,7 @@
       root.setAttribute("revision", revision);
       root.setAttribute("creator", Globals.getUser());
       root.setAttribute("when", Globals.getDateString());
-      if(extension.length() > 0)
-         root.setAttribute("extension", extension);
+      if(extension.length() > 0) root.setAttribute("extension", extension);
       try{
          DocumentHelper.writeDocument(doc, file);
       }catch(javax.xml.transform.TransformerConfigurationException tce){
@@ -123,12 +155,33 @@
          System.out.println("CreateRevision: IOException writing XML file.");
       }
       // Update Translation
-      FlatResource resource = (FlatResource) ((FlatContent) content).getResource(workUnid, language, "edit");
-      FlatTranslation translation = resource.getTranslation();
-      translation.setEdit(revision);
-      if(setLive)
-         translation.setLive(revision);
+      FlatResource resource;
+      if(ResourceTransformer.TYPE_DESIGN.equalsIgnoreCase(type)){
+         if(null == design){
+            System.out.println("CreateRevision Design: No Design.");
+            return;
+            // TODO: Throw exception.
+         }else{
+            resource = (FlatResource) design.getDesign(workUnid);
+         }
+      }else if(ResourceTransformer.TYPE_STRUCTURE.equalsIgnoreCase(type)){
+         if(null == design){
+            System.out.println("CreateRevision Structure: No Design.");
+            return;
+            // TODO: Throw exception.
+         }else{
+            resource = (FlatResource) design.getStructure(workUnid);
+         }
+      }else{
+         resource = (FlatResource) ((FlatContent) content).getResource(workUnid, language, "edit");
+      }
+      FlatTranslation translation = resource.getTranslation(language);
+      // TODO: Other NamedRevisions?
+      translation.setNamedRevision("edit", revision);
+      if(setLive || !ResourceTransformer.TYPE_CONTENT.equalsIgnoreCase(type)) translation.setNamedRevision(Content.REVISION_DEFAULT, revision);
       translation.save();
+      // Update Indexes
+      ((FlatContent) Globals.getPublication().getContent()).updateIndexes();
    }
    /**
     * Saves the asset to a file.
@@ -143,9 +196,7 @@
    static private void saveFileFromPart(File assetFile, Part part) throws Exception {
       if(!assetFile.exists()){
          boolean created = assetFile.createNewFile();
-         if(!created){
-            throw new RuntimeException("The file [" + assetFile + "] could not be created.");
-         }
+         if(!created){ throw new RuntimeException("The file [" + assetFile + "] could not be created."); }
       }
       byte[] buf = new byte[4096];
       FileOutputStream out = new FileOutputStream(assetFile);
@@ -172,8 +223,7 @@
       for(int i = 0; i < DUBLIN_CORE_PARAMETERS.length; i++){
          String paramName = DUBLIN_CORE_PARAMETERS[i];
          String paramValue = request.getParameter(UPLOADASSET_PARAM_PREFIX + paramName);
-         if(paramValue == null)
-            paramValue = "";
+         if(paramValue == null) paramValue = "";
          dublinCoreParams.put(paramName, paramValue);
       }
       return dublinCoreParams;

Modified: lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatContent.java
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatContent.java?rev=693670&r1=693669&r2=693670&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatContent.java (original)
+++ lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatContent.java Tue Sep  9 17:30:20 2008
@@ -1,20 +1,29 @@
 package org.apache.lenya.cms.content.flat;
 import java.io.File;
+import java.util.Set;
 import org.apache.lenya.cms.content.Content;
 import org.apache.lenya.cms.content.Resource;
+import org.apache.lenya.cms.modules.PublicationModules;
 /**
  * 
  * @author solprovider
  * @since 1.3
  */
 public class FlatContent implements Content {
-   File directory;
+   public static final String TYPE = "flat";
+   public static final String LANGUAGE_DEFAULT = "en";
+   static final String DIRECTORY_CONTENT = "resource";
+   static final String RELATIONS_DEFAULT = "live";
+   private File directoryResources;
    FlatIndexer indexer;
-   String[] languages = {"en"};
-   public FlatContent(File pdirectory, String[] planguages) {
-      directory = pdirectory;
-      languages = planguages;
-      indexer = new FlatIndexer(new File(directory, "index"), this);
+   String[] languages = {LANGUAGE_DEFAULT};
+   FlatDesign design;
+   public FlatContent(File directory, String[] languages, PublicationModules modules, FlatDesign design) {
+      // System.out.println("FlatContent");
+      directoryResources = new File(directory, DIRECTORY_CONTENT);
+      this.languages = languages;
+      indexer = new FlatIndexer(this, modules);
+      this.design = design;
       // The next line starts indexing everything in the background when Lenya starts.
       updateIndexes();
    }
@@ -35,18 +44,36 @@
       return resource.getNewURI();
    }
    public FlatRelations getRelations(String structure) {
-      return new FlatRelations(new File(directory, "relation" + File.separator + structure + ".xml"));
+      // Note: Added design to constructor because getRelations is called by FlatIndex before Globals.getPublication is usable.
+      // System.out.println("FlatContent.getRelations " + structure);
+      if(null == design){
+         System.out.println("FlatContent.getRelations: No Design. Using relation directory for " + structure);
+      }else{
+         Resource structureResource = design.getStructure(structure);
+         File file = new File(structureResource.getURI());
+         if(file.exists()){
+            // System.out.println("FlatContent.getRelations: Found DesignResource for " + structure);
+            return new FlatRelations(file);
+         }
+         // System.out.println("FlatContent.getRelations: No DesignResource. Using relation directory for " + structure);
+      }
+      // DEV: Needed for development with Structures in content/relation
+      return new FlatRelations(new File(directoryResources.getParentFile(), "relation" + File.separator + structure + ".xml"));
    }
    public Resource getResource(String unid) {
-      return (Resource) new FlatResource(directory, unid);
+      // System.out.println("FlatContent.getResource " + unid);
+      return (Resource) new FlatResource(directoryResources, unid);
    }
    public Resource getResource(String unid, String language, String revision) {
-      return (Resource) new FlatResource(directory, unid, language, revision);
+      // System.out.println("FlatContent.getResource UNID=" + unid + " LANG=" + language + " REV=" + revision);
+      return (Resource) new FlatResource(directoryResources, unid, language, revision);
    }
    public String[] getResources() {
-      return (new File(directory, "resource")).list();
+      return directoryResources.list();
    }
    public String getUNID(String structure, String id) {
+      // System.out.println("FlatContent.getUNID s=" + structure + " id='" + id + "'");
+      if((0 == id.length()) || (0 == structure.length())) return "";
       FlatRelations relations = getRelations(structure);
       return relations.getUNID(id);
    }
@@ -58,6 +85,15 @@
     * Updates Indexes in background.
     */
    void updateIndexes() {
-         new Thread((Runnable) indexer).start();
+      new Thread((Runnable) indexer).start();
+   }
+   public Set getStructures() {
+      return indexer.getStructures();
+   }
+   public Set getRevisions() {
+      return indexer.getRevisions();
+   }
+   public File getDirectory() {
+      return directoryResources;
    }
 }

Added: lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatDesign.java
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatDesign.java?rev=693670&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatDesign.java (added)
+++ lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatDesign.java Tue Sep  9 17:30:20 2008
@@ -0,0 +1,99 @@
+package org.apache.lenya.cms.content.flat;
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import org.apache.lenya.cms.content.Resource;
+import org.apache.lenya.util.Globals;
+/**
+ * 
+ * @author solprovider
+ * @since 1.3
+ */
+public class FlatDesign {
+   public static final String DESIGN_LANGUAGE = "xx";
+   static final String SEPARATOR_DESIGN = "$";
+   static final String SEPARATOR_RELATIONS = "+";
+   static final String DIRECTORY_DESIGN = "design";
+   private File directoryResources;
+   private String publicationId;
+   public FlatDesign(File directory, String publicationId) {
+      directoryResources = new File(directory, DIRECTORY_DESIGN);
+      if(!directoryResources.exists()) directoryResources.mkdirs();
+      this.publicationId = publicationId;
+   }
+   private Resource getResource(String unid) {
+      return (Resource) new FlatResource(directoryResources, unid, DESIGN_LANGUAGE);
+   }
+   private Resource getResource(String unid, String revision) {
+      System.out.println("FlatDesign.getResource UNID=" + unid + " REV=" + revision);
+      return (Resource) new FlatResource(directoryResources, unid, DESIGN_LANGUAGE, revision);
+   }
+   public String[] getResources() {
+      return directoryResources.list();
+   }
+   // New for Design
+   public Resource getDesign(String filename) {
+      return getResource(getDesignUnid(filename));
+   }
+   public Resource getDesign(String filename, String revision) {
+      return getResource(getDesignUnid(filename), revision);
+   }
+   public Resource getStructure(String name) {
+      return getResource(getStructureUnid(name));
+   }
+   public Resource getStructure(String name, String revision) {
+      return getResource(getStructureUnid(name), revision);
+   }
+   public File getDirectory() {
+      return directoryResources;
+   }
+   /**
+    * Transforms filename into a string acceptable as a directory name.<br>
+    * Process must be repeatable with consistent result for a given filename and not duplicate results for other filenames. <br>
+    * Used by getDesignUnid
+    * 
+    * @param filename
+    * @return
+    */
+   private static String makeSafe(String filename) {
+      // TODO: Does this work? for all OSes?
+      String ret = filename;
+      try{
+         ret = URLEncoder.encode(filename, "UTF-8");
+      }catch(UnsupportedEncodingException e){
+         ret = ret.replaceAll("[^a-zA-Z1-90]", SEPARATOR_DESIGN);
+      }
+      ret = ret.replaceAll("\u002A", "%2A"); // Asterisk is legal for URL encoding, but not legal directory name.
+      return ret;
+   }
+   /**
+    * Function to standardize translation of Module filename into a String that is safe as a directory name
+    * 
+    * @param filename
+    * @return UNID of Design Resource
+    */
+   public static String getDesignUnid(String filename) {
+      // /[pubID]/[moduleId]/filename
+      String publicationId = "";
+      String moduleId = "";
+      String filepath = "";
+      String[] parts = filename.split("/", 4);
+      if(4 > parts.length) return "";
+      if(0 != parts[0].length()) return "";
+      if(0 == parts[1].length()){
+         publicationId = Globals.getPublication().getId();
+      }else{
+         publicationId = parts[1];
+      }
+      if(0 == parts[2].length()){
+         moduleId = Globals.getModuleId();
+      }else{
+         moduleId = parts[2];
+      }
+      filepath = FlatDesign.makeSafe(parts[3]);
+      return publicationId + SEPARATOR_DESIGN + moduleId + SEPARATOR_DESIGN + filepath;
+   }
+   public String getStructureUnid(String structure) {
+      return publicationId + FlatDesign.SEPARATOR_RELATIONS + structure;
+   }
+}

Modified: lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndex.java
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndex.java?rev=693670&r1=693669&r2=693670&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndex.java (original)
+++ lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndex.java Tue Sep  9 17:30:20 2008
@@ -1,9 +1,11 @@
 package org.apache.lenya.cms.content.flat;
 import java.io.File;
+import java.io.IOException;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
-import org.apache.lenya.xml.DocumentHelper;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.lenya.util.Globals;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
@@ -12,132 +14,160 @@
  * @author solprovider
  * @since 1.3
  */
-public class FlatIndex {
-   File configurationFile = null;
-   File indexFile;
+class FlatIndex {
+   private static final String LANGUAGE_ALL = "ALLINDEX";
    FlatContent content;
-   String indexName;
-   String language = "";
+   volatile Map files = new HashMap(); // files(language) = filename String
    String structure = "";
    String revision = "live";
    Map filter = new HashMap();
    Map include = new HashMap();
-   public FlatIndex(FlatContent content, File indexDirectory, String indexName, String language) {
-      if(null == indexName){ // SitetreeGenerator called without src attribute.
-         this.indexName = "";
-      }else{
-         this.indexName = indexName;
-      }
+   String name = "";
+   boolean isAll = false;
+   FlatIndex(FlatContent content) {
+      // System.out.println("FlatIndex ALL");
       this.content = content;
-      if(0 == this.indexName.length()){ // Special case: all Resources disregarding Translations
-         indexFile = new File(indexDirectory, "all.xml");
-      }else{
-         this.language = language;
-         configurationFile = new File(indexDirectory, indexName + ".xconf");
-         indexFile = new File(indexDirectory, indexName + "_" + language + ".xml");
-      }
+      isAll = true;
+      include.put("type", new FlatIndexPart("type"));
+      include.put("id", new FlatIndexPart("id"));
    }
-   private void loadConfiguration() {
-      if(null == configurationFile){ // Special case: all Resources disregarding Translations
-         include.put("unid", new FlatIndexPart("unid"));
-         include.put("type", new FlatIndexPart("type"));
-         include.put("doctype", new FlatIndexPart("doctype"));
-         include.put("id", new FlatIndexPart("id"));
-      }else{
-         Document document;
-         try{
-            document = DocumentHelper.readDocument(configurationFile);
-         }catch(javax.xml.parsers.ParserConfigurationException pce){
-            System.out.println("Indexer: could not parse " + configurationFile.getPath());
-            return;
-         }catch(org.xml.sax.SAXException saxe){
-            System.out.println("Indexer: " + configurationFile.getPath() + " is not valid.");
-            return;
-         }catch(java.io.IOException ioe){
-            System.out.println("Indexer: could not read " + configurationFile.getPath());
-            return;
-         }
-         Element root = document.getDocumentElement();
-         if(root.hasAttribute("structure")) structure = root.getAttribute("structure");
-         if(root.hasAttribute("revision")) revision = root.getAttribute("revision");
-         NodeList nl;
-         int length;
-         int i;
-         nl = root.getElementsByTagName("filter");
-         length = nl.getLength();
-         for(i = 0; i < length; i++){
-            FlatIndexPart part = new FlatIndexPart((Element) nl.item(i));
+   FlatIndex(String name, Configuration config, FlatContent content) {
+      // System.out.println("FlatIndex " + name);
+      this.name = name;
+      this.content = content;
+      structure = config.getAttribute("structure", structure);
+      revision = config.getAttribute("revision", revision);
+      // For each element
+      Configuration[] children = config.getChildren();
+      for(int c = 0; c < children.length; c++){
+         Configuration child = children[c];
+         String element = child.getName();
+         if(element.equalsIgnoreCase("flter")){
+            FlatIndexPart part = new FlatIndexPart(child);
             filter.put(part.getName(), part);
          }
-         nl = root.getElementsByTagName("include");
-         length = nl.getLength();
-         for(i = 0; i < length; i++){
-            FlatIndexPart part = new FlatIndexPart((Element) nl.item(i));
+         if(element.equalsIgnoreCase("include")){
+            FlatIndexPart part = new FlatIndexPart(child);
             include.put(part.getName(), part);
          }
-         include.put("unid", new FlatIndexPart("unid"));
-         include.put("type", new FlatIndexPart("type"));
-         include.put("doctype", new FlatIndexPart("doctype"));
-         include.put("id", new FlatIndexPart("id"));
-         include.put("title", new FlatIndexPart("title"));
-         include.put("href", new FlatIndexPart("href"));
-         include.put("extension", new FlatIndexPart("extension"));
       }
+      include.put("unid", new FlatIndexPart("unid"));
+      include.put("type", new FlatIndexPart("type"));
+      include.put("doctype", new FlatIndexPart("doctype"));
+      include.put("id", new FlatIndexPart("id"));
+      include.put("title", new FlatIndexPart("title"));
+      include.put("href", new FlatIndexPart("href"));
+      include.put("extension", new FlatIndexPart("extension"));
    }
-   public String getIndexFilename() {
-      if(!indexFile.exists()) update();
-      return indexFile.getPath();
-   }
-   public void update() {
-      // TODO: Add publication ID to the log.
-      // System.out.println("Indexer updating " + indexName + "(" + language + ")");
-      loadConfiguration();
+   void update() {
+      // System.out.println("FlatIndexer.update");
+      if(isAll){
+         update("");
+         return;
+      }
+      String[] languages = content.getLanguages();
+      int languagesLength = languages.length;
+      for(int l = 0; l < languagesLength; l++){
+         String language = languages[l];
+         update(language);
+      }
+   }
+   /**
+    * 
+    * @param language
+    * @return Absolute filename of index
+    */
+   String update(String language) {
+      // System.out.println("FlatIndex.update " + name + " language=" + language);
       // Init Document
       Document document;
       try{
          document = org.apache.lenya.xml.DocumentHelper.createDocument("", "index", null);
       }catch(javax.xml.parsers.ParserConfigurationException pce){
          System.out.println("FlatIndex: ParserConfigurationException");
-         return;
+         return "";
       }
       Element root = document.getDocumentElement();
-      root.setAttribute("name", indexName);
+      root.setAttribute("name", name);
       root.setAttribute("language", language);
       // Update
       if(structure.length() > 0){
          include.put("fullid", new FlatIndexPart("fullid"));
-         updateStructure(document, root);
-      }else if(0 < this.indexName.length()){
-         updateFlat(document, root);
-      }else{ // Special case: all Resources disregarding Translations
+         updateStructure(document, root, language);
+      }else if(0 < this.name.length()){
+         updateFlat(document, root, language);
+      }else{
+         // SitetreeGenerator called without src attribute.
+         // Special case: all Resources disregarding Translations
          updateAll(document, root);
       }
+      // Get File
+      File indexFile = getFile(language);
       // Write document
+      // System.out.println("FlatIndex: Writing " + indexFile.getAbsolutePath());
       try{
          org.apache.lenya.xml.DocumentHelper.writeDocument(document, indexFile);
+         // System.out.println("Indexing " + name + "_" + language + " completed.");
       }catch(javax.xml.transform.TransformerConfigurationException tce){
-         System.out.println("FlatIndex: TransformerConfigurationException");
+         System.out.println("FlatIndex: TransformerConfigurationException" + name + "_" + language);
       }catch(javax.xml.transform.TransformerException te){
-         System.out.println("FlatIndex: TransformerException");
+         System.out.println("FlatIndex: TransformerException" + name + "_" + language);
       }catch(java.io.IOException ioe){
-         System.out.println("FlatIndex: IOException");
+         System.out.println("FlatIndex: IOException" + name + "_" + language);
+      }catch(Exception e){
+         System.out.println("FlatIndex: Unknown Exception - " + name + "_" + language + "\n" + e.getLocalizedMessage());
       }
-      // System.out.println("Indexing " + indexName + "_" + language + " Completed");
+      return indexFile.getAbsolutePath();
    }
-   private void updateStructure(Document document, Element root) {
+   private synchronized File getFile(String language) {
+      File indexFile;
+      if(isAll){
+         if(files.containsKey(LANGUAGE_ALL)){
+            indexFile = new File((String) files.get(LANGUAGE_ALL));
+         }else{
+            try{
+               indexFile = File.createTempFile("all", ".xml");
+            }catch(IOException e){
+               indexFile = new File(Globals.getPublication().getContentDirectory(), "all.xml");
+            }
+            indexFile.deleteOnExit();
+            files.put(LANGUAGE_ALL, indexFile.getAbsolutePath());
+         }
+      }else{
+         if(files.containsKey(language)){
+            indexFile = new File((String) files.get(language));
+         }else{
+            try{
+               indexFile = File.createTempFile(name, "_" + language + ".xml");
+            }catch(IOException e){
+               indexFile = new File(Globals.getPublication().getContentDirectory(), name + "_" + language + ".xml");
+            }
+            indexFile.deleteOnExit();
+            files.put(language, indexFile.getAbsolutePath());
+         }
+      }
+      // System.out.println("FlatIndex.getFile " + indexFile.getName());
+      return indexFile;
+   }
+   private void updateStructure(Document document, Element root, String language) {
+      // System.out.println("FlatIndexer.updateStructure " + name + " Structure='" + structure + "'");
       FlatRelations relations = content.getRelations(structure);
+      if(null == relations){
+         System.out.println("FlatIndexer.updateStructure " + name + " Structure '" + structure + "' was null");
+         return;
+      }
       Element resourceElement = relations.getRoot();
       if(null == resourceElement){
-         System.out.println("Error creating Index " + indexName + "_" + language + ".  Could not find Structure " + structure);
+         System.out.println("Error creating Index " + name + "_" + language + ".  Could not find Structure " + structure);
       }else{
-         addStructureResource(document, root, resourceElement, "");
+         addStructureResource(document, root, resourceElement, "", language);
       }
    }
    /**
     * Add child "resource" elements of resourceElement to root, and recurse for each. Must pass filters.
     */
    // private void addStructureResource(Document document, Element root, Element resourceElement, String parenttype, String parentdoctype) {
-   private void addStructureResource(Document document, Element root, Element resourceElement, String parenttype) {
+   private void addStructureResource(Document document, Element root, Element resourceElement, String parenttype, String language) {
       // NodeList children = resourceElement.getElementsByTagName("resource"); //getDescendants, need getChildren
       NodeList children = resourceElement.getChildNodes();
       int length = children.getLength();
@@ -173,13 +203,14 @@
                   }
                   // INCLUDE - END
                   // addStructureResource(document, element, resourceChild, fulltype, fulldoctype);
-                  addStructureResource(document, element, resourceChild, fulltype);
+                  addStructureResource(document, element, resourceChild, fulltype, language);
                } // if useResource
             } // if resource not null
          } // if "resource"
       } // for
    } // function
-   private void updateFlat(Document document, Element root) {
+   private void updateFlat(Document document, Element root, String language) {
+      // System.out.println("FlatIndexer.updateFlat " + name);
       // Build Index
       String[] unids = content.getResources();
       int unidsLength = unids.length;
@@ -212,14 +243,14 @@
       } // for
    }
    private void updateAll(Document document, Element root) {
-      // System.out.println("updateAll BEGIN");
+      // System.out.println("FlatIndexer.updateAll");
       root.setAttribute("description", "Special index containing all Resources ignoring existence of Translations: no filtering by language and no information from Translations and Revisions.");
       // Build Index
       String[] unids = content.getResources();
       int unidsLength = unids.length;
       for(int u = 0; u < unidsLength; u++){
          String unid = unids[u];
-         FlatResource resource = (FlatResource) content.getResource(unid, language, revision);
+         FlatResource resource = (FlatResource) content.getResource(unid);
          FlatIndexPart part;
          // INCLUDE - BEGIN
          Element element = addElement(document, root, "resource");
@@ -232,16 +263,18 @@
          }
          // Add translations with language and title.
          String[] languages = resource.getLanguages();
-         for(int l = 0; l < languages.length; l++){
-            Element translationElement = addElement(document, element, "translation");
-            translationElement.setAttribute("language", languages[l]);
-            FlatTranslation translation = resource.getTranslation(languages[l], false);
-            if(null != translation){
-               FlatRevision revision = translation.getRevision();
-               if(null != revision){
-                  String title = revision.getTitle();
-                  if(title.length() > 0){
-                     translationElement.setAttribute("title", title);
+         if(null != languages){
+            for(int l = 0; l < languages.length; l++){
+               Element translationElement = addElement(document, element, "translation");
+               translationElement.setAttribute("language", languages[l]);
+               FlatTranslation translation = resource.getTranslation(languages[l], false);
+               if(null != translation){
+                  FlatRevision revision = translation.getRevision();
+                  if(null != revision){
+                     String title = revision.getTitle();
+                     if(title.length() > 0){
+                        translationElement.setAttribute("title", title);
+                     }
                   }
                }
             }
@@ -254,4 +287,17 @@
       parent.appendChild(newElement);
       return newElement;
    }
+   String getFilename(String language) {
+      // System.out.println("FlatIndex.getFilename " + name + " l=" + language);
+      if(isAll) language = LANGUAGE_ALL;
+      String filename = (String) files.get(language);
+      if(null == filename) filename = update(language);
+      return filename;
+   }
+   String getStructure() {
+      return structure;
+   }
+   String getRevision() {
+      return revision;
+   }
 }

Modified: lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndexPart.java
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndexPart.java?rev=693670&r1=693669&r2=693670&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndexPart.java (original)
+++ lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndexPart.java Tue Sep  9 17:30:20 2008
@@ -1,5 +1,6 @@
 package org.apache.lenya.cms.content.flat;
 import java.util.StringTokenizer;
+import org.apache.avalon.framework.configuration.Configuration;
 import org.w3c.dom.Element;
 /**
  * 
@@ -15,18 +16,23 @@
          property = element.getAttribute("property");
          name = property;
       }
-      if(element.hasAttribute("name"))
-         property = element.getAttribute("name");
+      if(element.hasAttribute("name")) property = element.getAttribute("name");
       if(null != element.getFirstChild()){
          value = element.getFirstChild().getNodeValue();
-         if(null == value)
-            value = "";
+         if(null == value) value = "";
       }
    }
    public FlatIndexPart(String variable) {
       name = variable;
       property = variable;
    }
+   public FlatIndexPart(Configuration config) {
+      // TODO: This looks backwards. Check and fix Element version too.
+      property = config.getAttribute("property", property);
+      name = property;
+      property = config.getAttribute("name", property);
+      config.getValue("");
+   }
    public String getName() {
       return name;
    }
@@ -38,20 +44,15 @@
    }
    public boolean check(String test) {
       // System.out.print(" T=" + test + " V=" + value);
-      if(test.length() < 1)
-         return true;
-      if(test.equals("/"))
-         return true; // Structured indexes add slash prefix.
-      if(test.equalsIgnoreCase("true"))
-         return true;
+      if(test.length() < 1) return true;
+      if(test.equals("/")) return true; // Structured indexes add slash prefix.
+      if(test.equalsIgnoreCase("true")) return true;
       String token;
       StringTokenizer tokens = new StringTokenizer(value, "|,;");
       do{
          token = tokens.nextToken();
-         if(test.equals(token))
-            return true;
-         if(test.endsWith(token))
-            return true;
+         if(test.equals(token)) return true;
+         if(test.endsWith(token)) return true;
       }while(tokens.hasMoreTokens());
       // System.out.print(" FALSE ");
       return false;

Modified: lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndexer.java
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndexer.java?rev=693670&r1=693669&r2=693670&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndexer.java (original)
+++ lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatIndexer.java Tue Sep  9 17:30:20 2008
@@ -1,5 +1,13 @@
 package org.apache.lenya.cms.content.flat;
 import java.io.File;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.lenya.cms.modules.Module;
+import org.apache.lenya.cms.modules.PublicationModules;
 /**
  * FlatContent handles threading. This class could be nested in FlatContent.
  * 
@@ -7,28 +15,75 @@
  * @since 1.3
  */
 class FlatIndexer implements Runnable {
-   // TODO: Build list of Index configurations from Modules. Move .xconf files to Modules. Change extension (to .icx, .xic, .index?)
+   /**
+    * @deprecated indexDirectory was used for loading indexes from one directory.
+    */
    File indexDirectory;
    FlatContent content;
+   FlatIndex allIndex;
+   Map indexes = new HashMap();
+   Set structures = new TreeSet();
+   Set revisions = new TreeSet();
    private volatile boolean isRunning = false;
    private volatile boolean runAgain = false; //
    private Object lock = new Object(); // for locking synchronization.
-   FlatIndexer(File pindexDirectory, FlatContent pcontent) {
-      indexDirectory = pindexDirectory;
-      content = pcontent;
+   /**
+    * Loads configuration from PublicationModules.
+    * 
+    * @param content
+    * @param modules
+    * 
+    */
+   FlatIndexer(FlatContent content, PublicationModules modules) {
+      // System.out.println("FlatIndexer");
+      revisions.add("live");
+      revisions.add("edit");
+      this.content = content;
+      loadIndexes(modules.getSourceModules());
+   }
+   /**
+    * 
+    * @param modules -
+    *           Map(?) = Module
+    */
+   private void loadIndexes(Map modules) {
+      allIndex = new FlatIndex(content);
+      // TODO: Prioritize indexes? Currently just overwrites duplicate without thought.
+      Map indexConfigurations = new HashMap();
+      Iterator iterator = modules.entrySet().iterator();
+      while(iterator.hasNext()){
+         Map.Entry entry = (Map.Entry) iterator.next();
+         Module module = (Module) entry.getValue();
+         indexConfigurations.putAll(module.getIndexes());
+      }
+      iterator = indexConfigurations.entrySet().iterator();
+      while(iterator.hasNext()){
+         Map.Entry entry = (Map.Entry) iterator.next();
+         String id = (String) entry.getKey();
+         if(!indexes.containsKey(id)){
+            Configuration config = (Configuration) entry.getValue();
+            FlatIndex index = new FlatIndex(id, config, content);
+            indexes.put(id, index);
+            // System.out.println("FlatIndexer.loadIndexes added " + id);
+            String structure = index.getStructure();
+            if(0 < structure.length()){
+               structures.add(structure);
+            }
+            String revision = index.getRevision();
+            if(0 < revision.length()){
+               revisions.add(revision);
+            }
+         }
+      }
    }
    public void run() {
       // Only the first thread updates. Additional requests set flag so the first thread will repeat the update.
       // runAgain cannot be false on later threads unless the Indexer is updating
       // If already queued, do nothing.
-      if(runAgain){
-         return;
-      }
+      if(runAgain){ return; }
       runAgain = true;
       // Set to run, but return if already running,
-      if(isRunning){
-         return;
-      }
+      if(isRunning){ return; }
       // synchronized so two threads do not conflict if both believe are first thread.
       synchronized (lock){
          isRunning = true;
@@ -45,53 +100,42 @@
     * Updates all Indexes.
     */
    void update() {
-      System.out.println("Starting Indexer for " + indexDirectory.getAbsolutePath());
-      updateIndexAll();
-      if(!indexDirectory.exists()) return;
-      // System.out.println("Starting Indexer UpdateAll");
-      String[] files = indexDirectory.list();
-      // System.out.println("FlatIndexer.updateAll ID=" + indexDirectory.getPath());
-      if(null == files) return;
-      int filesLength = files.length;
-      for(int f = 0; f < filesLength; f++){
-         String filename = files[f];
-         if(filename.endsWith(".xconf")){
-            String indexName = filename.substring(0, filename.lastIndexOf(".xconf"));
-            String[] languages = content.getLanguages();
-            int languagesLength = languages.length;
-            for(int l = 0; l < languagesLength; l++){
-               String language = languages[l];
-               FlatIndex index = new FlatIndex(content, indexDirectory, indexName, language);
-               index.update();
-            }
-         }
+      // System.out.println("FlatIndexer.update");
+      // Update the all Resources index (ignores Translations and Revisions).
+      allIndex.update();
+      Iterator iterator = indexes.entrySet().iterator();
+      while(iterator.hasNext()){
+         Map.Entry entry = (Map.Entry) iterator.next();
+         FlatIndex index = (FlatIndex) entry.getValue();
+         index.update();
       }
    }
    /**
-    * Updates all Indexes for one language.
+    * Updates "ALL" Index without threading.
+    */
+   void updateAllIndex() {
+      allIndex.update();
+   }
+   /**
+    * Updates all Indexes for one language. Cannot be called - needs integration with threading system.
     * 
     * @param language
     */
-   void update(String language) {
-      updateIndexAll();
-      if(!indexDirectory.exists()) return;
-      String[] files = indexDirectory.list();
-      if(null == files) return;
-      int filesLength = files.length;
-      for(int f = 0; f < filesLength; f++){
-         String filename = files[f];
-         if(filename.endsWith(".xconf")){
-            String indexName = filename.substring(0, filename.lastIndexOf(".xconf"));
-            FlatIndex index = new FlatIndex(content, indexDirectory, indexName, language);
-            index.update();
-         }
-      }
-   }
-   private void updateIndexAll() {
-      // Update the all Resources index (ignores Translations and Revisions).
-      FlatIndex index = new FlatIndex(content, indexDirectory, "", "");
-      index.update();
-   }
+   // private void update(String language) {
+   // System.out.println("FlatIndexer.update language=" + language);
+   //
+   // updateIndexAll();
+   // Iterator iterator = indexes.entrySet().iterator();
+   // while(iterator.hasNext()){
+   // Map.Entry entry = (Map.Entry) iterator.next();
+   // FlatIndex index = (FlatIndex) entry.getValue();
+   // index.update(language);
+   // }
+   // }
+   // private void updateIndexAll() {
+   // // Update the all Resources index (ignores Translations and Revisions).
+   // allIndex.update();
+   // }
    /**
     * 
     * @param indexName
@@ -99,6 +143,16 @@
     * @return filename of specified Index
     */
    public String getIndexFilename(String indexName, String language) {
-      return (new FlatIndex(content, indexDirectory, indexName, language)).getIndexFilename();
+      // System.out.println("FlatIndexer.getIndexFilename " + indexName + " l=" + language);
+      if((null != indexName) && (0 < indexName.length())){
+         if(indexes.containsKey(indexName)){ return(((FlatIndex) indexes.get(indexName)).getFilename(language)); }
+      }
+      return allIndex.getFilename("");
+   }
+   Set getStructures() {
+      return structures;
+   }
+   Set getRevisions() {
+      return revisions;
    }
 }

Modified: lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatRelations.java
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatRelations.java?rev=693670&r1=693669&r2=693670&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatRelations.java (original)
+++ lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatRelations.java Tue Sep  9 17:30:20 2008
@@ -80,6 +80,6 @@
       return "";
    }
    private void update() {
-      // WORK: Reset if file modified
+      // TODO: Reset if file modified
    }
 }

Modified: lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatResource.java
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatResource.java?rev=693670&r1=693669&r2=693670&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatResource.java (original)
+++ lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatResource.java Tue Sep  9 17:30:20 2008
@@ -2,8 +2,10 @@
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
 import javax.xml.parsers.ParserConfigurationException;
+import org.apache.lenya.cms.content.Content;
 import org.apache.lenya.cms.content.Location;
 import org.apache.lenya.cms.content.Resource;
 import org.apache.lenya.cms.content.ResourceException;
@@ -21,6 +23,7 @@
  */
 public class FlatResource implements Resource {
    private static final String FILENAME_RESOURCE = "resource.xml";
+   private static final String ATTR_DEFAULT_LANGUAGE = "defaultlanguage";
    private File contentDirectory;
    private File resourceDirectory;
    private Document resource;
@@ -29,42 +32,45 @@
    private String id = "";
    private String type = "";
    private String doctype = "";
-   private String defaultLanguage = "en";
+   private String defaultLanguage = FlatContent.LANGUAGE_DEFAULT;
    private String defaultLanguageParameter = "";
-   private String defaultRevision = "live";
+   private String defaultRevision = Content.REVISION_DEFAULT;
    // private String extension = ""; //Moved to revision
    private String[] languages;
    boolean isChanged = false;
    public FlatResource(File directory, String unid, String language, String revision) {
+      // System.out.println("FlatResource new unid=" + unid + "_" + language + "!" + revision + " " + directory.getAbsolutePath());
       contentDirectory = directory;
       this.unid = unid;
-      if(language.length() > 0)
-         defaultLanguage = language;
+      if((null == language) || (0 < language.length())) defaultLanguage = language;
       defaultRevision = revision;
       init(false);
    }
    public FlatResource(File directory, String unid, String language) {
+      // System.out.println("FlatResource new unid=" + unid + "_" + language + " " + directory.getAbsolutePath());
       contentDirectory = directory;
       this.unid = unid;
-      if(language.length() > 0)
-         defaultLanguage = language;
+      if(language.length() > 0) defaultLanguage = language;
       init(false);
    }
    public FlatResource(File directory, String unid) {
+      // System.out.println("FlatResource new unid=" + unid + " " + directory.getAbsolutePath());
       contentDirectory = directory;
       this.unid = unid;
       init(true);
    }
    private void init(boolean useDefaultLanguage) {
-      // System.out.println("FlatResource.init BEGIN UNID=" + unid);
+      // System.out.println("FlatResource.init unid=" + unid + " " + contentDirectory.getAbsolutePath());
       boolean workUseDefaultLanguage = useDefaultLanguage;
       Location location = new Location(unid);
       // Remove extra parts.
       unid = location.getUnid();
       // Revision
+      // System.out.println("FlatResource.init REV1=" + defaultRevision);
       String tmpString = location.getRevision();
       if(0 < tmpString.length()){
          defaultRevision = tmpString;
+         // System.out.println("FlatResource.init REV2=" + defaultRevision);
       }
       // Language
       tmpString = location.getLanguage();
@@ -76,7 +82,7 @@
             defaultLanguage = defaultLanguageParameter;
          }
       }
-      resourceDirectory = new File(contentDirectory, "resource" + File.separator + unid);
+      resourceDirectory = new File(contentDirectory, unid);
       Publication pub = Globals.getPublication();
       if(null != pub){
          // Use Publication's Default Language. Only possible during Request.
@@ -90,48 +96,71 @@
          if(!resourceDirectory.exists()){
             // Check structure named before first slash
             // DESIGN: Use String.split()?
-            String structure = "live";
+            String structure = FlatContent.RELATIONS_DEFAULT;
             if(pos > 0){
                structure = workUnid.substring(0, pos);
                workUnid = workUnid.substring(pos);
             }
-            workUnid = pub.getContent().getUNID(structure, workUnid);
-            if(0 != workUnid.length()){
-               resourceDirectory = new File(contentDirectory, "resource" + File.separator + workUnid);
+            // Do not test if no structure or when seeking itself.
+            // if((0 < structure.length()) && !workUnid.endsWith(FlatContent.SEPARATOR_RELATIONS + structure)){
+            if((0 < structure.length()) && !workUnid.endsWith(structure)){
+               // System.out.println("FlatResource.init Check Structure=" + structure);
+               workUnid = pub.getContent().getUNID(structure, workUnid);
+               if(0 != workUnid.length()){
+                  resourceDirectory = new File(contentDirectory, workUnid);
+               }
             }
          }
          if(!resourceDirectory.exists()){
-            // Check live structure
-            workUnid = pub.getContent().getUNID("live", unid);
-            if(0 != workUnid.length()){
-               resourceDirectory = new File(contentDirectory, "resource" + File.separator + workUnid);
+            // Check default structure without part before slash
+            // Do not test default structure when seeking default Structure Design Resource
+            // if(!workUnid.endsWith(FlatContent.SEPARATOR_RELATIONS + FlatContent.RELATIONS_DEFAULT)){
+            if(!workUnid.endsWith(FlatContent.RELATIONS_DEFAULT)){
+               // System.out.println("FlatResource.init Check default Structure partialUnid=" + workUnid);
+               workUnid = pub.getContent().getUNID(FlatContent.RELATIONS_DEFAULT, unid);
+               if(0 != workUnid.length()){
+                  resourceDirectory = new File(contentDirectory, workUnid);
+               }
             }
          }
-         unid = workUnid;
+         if(!resourceDirectory.exists()){
+            // Check default structure using entire unid
+            workUnid = unid;
+            // Do not test default structure when seeking default Structure Design Resource
+            // if(!workUnid.endsWith(FlatContent.SEPARATOR_RELATIONS + FlatContent.RELATIONS_DEFAULT)){
+            if(!workUnid.endsWith(FlatContent.RELATIONS_DEFAULT)){
+               // System.out.println("FlatResource.init Check Default Structure with unid=" + workUnid);
+               workUnid = pub.getContent().getUNID(FlatContent.RELATIONS_DEFAULT, unid);
+               if(0 != workUnid.length()){
+                  resourceDirectory = new File(contentDirectory, workUnid);
+               }
+            }
+         }
+         if(resourceDirectory.exists()){
+            unid = workUnid;
+         }
       }
       // System.out.println("FlatResource.init USING UNID=" + unid);
       if(!resourceDirectory.exists()){
+         // System.out.println("FlatResource.init Could not find unid '" + unid + "' at " + resourceDirectory.getAbsolutePath());
          return;
       }
+      // System.out.println("FlatResource.init Loading");
       try{
          resource = DocumentHelper.readDocument(new File(resourceDirectory, FILENAME_RESOURCE));
          root = resource.getDocumentElement();
-         if(root.hasAttribute("defaultlanguage")){
-            defaultLanguageParameter = root.getAttribute("defaultlanguage");
+         if(root.hasAttribute(ATTR_DEFAULT_LANGUAGE)){
+            defaultLanguageParameter = root.getAttribute(ATTR_DEFAULT_LANGUAGE);
          }
-         if(root.hasAttribute("doctype"))
-            doctype = root.getAttribute("doctype");
-         if(root.hasAttribute("type"))
-            type = root.getAttribute("type");
-         if(root.hasAttribute("id"))
-            id = root.getAttribute("id");
+         if(root.hasAttribute("doctype")) doctype = root.getAttribute("doctype");
+         if(root.hasAttribute("type")) type = root.getAttribute("type");
+         if(root.hasAttribute("id")) id = root.getAttribute("id");
          String[] files = resourceDirectory.list();
          int length = files.length;
          List list = new ArrayList();
          for(int i = 0; i < length; i++){
             File file = new File(resourceDirectory, files[i]);
-            if(file.isDirectory())
-               list.add(files[i]);
+            if(file.isDirectory()) list.add(files[i]);
          }
          languages = (String[]) list.toArray(new String[0]);
          Arrays.sort(languages);
@@ -229,10 +258,9 @@
     */
    // public String get(String property, String fullid, String fulltype, String fulldoctype) {
    public String get(String property, String fullid, String fulltype) {
-      if(property.equalsIgnoreCase("type")){
-         return fulltype;
-         // }else if(property.equalsIgnoreCase("doctype")){
-         // return fulldoctype;
+      if(property.equalsIgnoreCase("type")){ return fulltype;
+      // }else if(property.equalsIgnoreCase("doctype")){
+      // return fulldoctype;
       }
       return get(property, fullid);
    }
@@ -240,9 +268,7 @@
     * Get variable for Structured Index Filters
     */
    public String get(String property, String fullid) {
-      if(property.equalsIgnoreCase("fullid")){
-         return fullid;
-      }
+      if(property.equalsIgnoreCase("fullid")){ return fullid; }
       return get(property);
    }
    /**
@@ -265,9 +291,7 @@
          return getLanguage();
       }else if(property.equalsIgnoreCase("fullid")){
          return getID();
-      }else if(property.equalsIgnoreCase("href")){
-         return getHREF();
-      }
+      }else if(property.equalsIgnoreCase("href")){ return getHREF(); }
       return getXPath(property);
    }
    private String getXPath(String property) {
@@ -280,18 +304,14 @@
       return getTranslation(language, true);
    }
    public FlatTranslation getTranslation(String language, boolean allowDefaultLanguage) {
-      if(allowDefaultLanguage){
-         return new FlatTranslation(resourceDirectory, language, defaultRevision, defaultLanguage);
-      }else
-         return new FlatTranslation(resourceDirectory, language, defaultRevision);
+      if(allowDefaultLanguage){ return new FlatTranslation(resourceDirectory, language, defaultRevision, defaultLanguage); }
+      return new FlatTranslation(resourceDirectory, language, defaultRevision);
    }
    public boolean hasRevision() {
       FlatTranslation translation = getTranslation(defaultLanguage, false);
-      if(null == translation)
-         return false;
+      if(null == translation) return false;
       FlatRevision revision = translation.getRevision(defaultRevision);
-      if(null == revision)
-         return false;
+      if(null == revision) return false;
       // DEV TEST
       // boolean exists = revision.exists();
       // if(getTitle().length() < 1){
@@ -316,36 +336,30 @@
       root.setAttribute("unid", unid);
       root.setAttribute("type", type);
       root.setAttribute("id", id);
-      if(defaultLanguageParameter.length() > 0)
-         root.setAttribute("defaultlanguage", defaultLanguageParameter);
-      if(doctype.length() > 0)
-         root.setAttribute("doctype", doctype);
+      if(defaultLanguageParameter.length() > 0) root.setAttribute(ATTR_DEFAULT_LANGUAGE, defaultLanguageParameter);
+      if(doctype.length() > 0) root.setAttribute("doctype", doctype);
       String tmp;
       if(null != languages){
          for(int l = 0; l < languages.length; l++){
             Element te = addElement(document, root, "translation");
             te.setAttribute("language", languages[l]);
             FlatTranslation translation = getTranslation(languages[l]);
-            tmp = translation.getEdit();
-            if(tmp.length() > 0)
-               te.setAttribute("edit", tmp);
-            tmp = translation.getLive();
-            if(tmp.length() > 0)
-               te.setAttribute("live", tmp);
+            // TODO: Use NamedRevisions - Content.getRevisions()
+            tmp = translation.getNamedRevision("edit");
+            if(tmp.length() > 0) te.setAttribute("edit", tmp);
+            tmp = translation.getNamedRevision(Content.REVISION_DEFAULT);
+            if(tmp.length() > 0) te.setAttribute(Content.REVISION_DEFAULT, tmp);
             String[] revisions = translation.getRevisions();
             for(int r = 0; r < revisions.length; r++){
                Element re = addElement(document, te, "revision");
                re.setAttribute("revision", revisions[r]);
                FlatRevision revision = translation.getRevision(revisions[r]);
                tmp = revision.getTitle();
-               if(tmp.length() > 0)
-                  re.setAttribute("title", tmp);
+               if(tmp.length() > 0) re.setAttribute("title", tmp);
                tmp = revision.getExtension();
-               if(tmp.length() > 0)
-                  re.setAttribute("extension", tmp);
+               if(tmp.length() > 0) re.setAttribute("extension", tmp);
                tmp = revision.getHREF();
-               if(tmp.length() > 0)
-                  re.setAttribute("href", tmp);
+               if(tmp.length() > 0) re.setAttribute("href", tmp);
             }
          }
       }
@@ -360,10 +374,8 @@
    public Document update(Document document) {
       // System.out.println("FlatResource.update - BEGIN");
       Element root = document.getDocumentElement();
-      if(root.hasAttribute("id"))
-         setID(root.getAttribute("id"));
-      if(root.hasAttribute("defaultlanguage"))
-         setDefaultLanguage(root.getAttribute("defaultlanguage"));
+      if(root.hasAttribute("id")) setID(root.getAttribute("id"));
+      if(root.hasAttribute(ATTR_DEFAULT_LANGUAGE)) setDefaultLanguage(root.getAttribute(ATTR_DEFAULT_LANGUAGE));
       save();
       NodeList translations = root.getElementsByTagName("translation");
       int translationslength = translations.getLength();
@@ -383,25 +395,23 @@
          // System.out.println("FlatResource.update - Get translation");
          if(exist){
             ft = getTranslation(language, false);
-            if(null == ft)
-               exist = false;
+            if(null == ft) exist = false;
          }
          // System.out.println("FlatResource.update - Update Translation");
          if(exist){
-            if(translation.hasAttribute("live"))
-               ft.setLive(translation.getAttribute("live"));
-            if(translation.hasAttribute("edit"))
-               ft.setEdit(translation.getAttribute("edit"));
+            // Use Content's NamedRevisions
+            Iterator iterator = ((FlatContent) Globals.getPublication().getContent()).getRevisions().iterator();
+            while(iterator.hasNext()){
+               String revisionName = (String) iterator.next();
+               if(translation.hasAttribute(revisionName)) ft.setNamedRevision(revisionName, translation.getAttribute(revisionName));
+            }
             NodeList revisions = translation.getElementsByTagName("revision");
             int revisionslength = revisions.getLength();
             for(int r = 0; r < revisionslength; r++){
-               // System.out.println("FlatResource.update - BEFORE");
                Element revision = (Element) revisions.item(r);
-               // System.out.println("FlatResource.update - AFTER");
                if(revision.hasAttribute("action")){
                   String action = revision.getAttribute("action");
                   if(action.equalsIgnoreCase("delete")){
-                     // System.out.println("FlatResource.update - Delete Revision");
                      String revisionid = revision.getAttribute("revision");
                      ft.deleteRevision(revisionid);
                   }
@@ -412,7 +422,6 @@
       }
       // Update Indexes
       ((FlatContent) Globals.getPublication().getContent()).updateIndexes();
-      // System.out.println("FlatResource.update - RETURN");
       return document;
    }
    private void setID(String newid) {
@@ -432,10 +441,9 @@
       // System.out.println("DELETE=" + translationDirectory.getAbsolutePath());
       deleteFile(translationDirectory);
    }
-   // TODO: Backup before delete. Use renameTo() to move outside the resource directory.
+   // TODO: Backup before delete. Use renameTo() to move outside the resource directory. See 13TODO.txt for design of transactions.
    private void deleteFile(File file) {
-      if(!file.exists())
-         return;
+      if(!file.exists()) return;
       if(file.isDirectory()){
          File[] files = file.listFiles();
          for(int f = 0; f < files.length; f++)
@@ -460,7 +468,7 @@
             return;
          }
          root = doc.getDocumentElement();
-         root.setAttribute("defaultlanguage", defaultLanguageParameter);
+         root.setAttribute(ATTR_DEFAULT_LANGUAGE, defaultLanguageParameter);
          root.setAttribute("id", id);
          try{
             DocumentHelper.writeDocument(doc, file);
@@ -471,21 +479,41 @@
          }catch(java.io.IOException ioe2){
             System.out.println("FlatResource.save - Could not write file: " + file.getAbsolutePath());
          }
-       }
+      }
       isChanged = false;
    }
    // <?xml version="1.0" encoding="UTF-8"?>
    // <resource defaultlanguage="en" doctype="xhtml" id="doctypes" type="xml" unid="0002" xmlns=""/>
    // TODO: Working here.
    // TODO: Create specific Exception
-   static public FlatResource create(String unid, String type, String id) throws ResourceException {
+   static public FlatResource createContent(String unid, String type, String id) throws ResourceException {
+      // System.out.println("FlatResource.createContent");
+      File contentDirectory = new File(Globals.getPublication().getContentDirectory(), FlatContent.DIRECTORY_CONTENT);
+      FlatResource resource = create(unid, type, id, contentDirectory, false);
+      // Only update "ALL" Index because cannot Resoruce cannot appear in other Indexes until a Revision is created.
+      ((FlatContent) Globals.getPublication().getContent()).indexer.updateAllIndex();
+      return resource;
+   }
+   static public FlatResource createDesign(String unid, String type, String id) throws ResourceException {
+      // System.out.println("FlatResource.createDesign");
+      FlatResource resource = create(FlatDesign.getDesignUnid(unid), type, id, Globals.getPublication().getDesign().getDirectory(), true);
+      return resource;
+   }
+   static public FlatResource createStructure(String unid, String type, String id) throws ResourceException {
+      System.out.println("FlatResource.createStructure");
+      FlatDesign design = Globals.getPublication().getDesign();
+      // FlatResource resource = create(FlatDesign.getStructureUnid(unid), type, id, Globals.getPublication().getDesign().getDirectory(), true);
+      FlatResource resource = create(design.getStructureUnid(unid), type, id, Globals.getPublication().getDesign().getDirectory(), true);
+      return resource;
+   }
+   static private FlatResource create(String unid, String type, String id, File contentDirectory, boolean isDesign) throws ResourceException {
+      // System.out.println("FlatResource.create DIR=" + contentDirectory.getAbsolutePath());
       String workUnid = unid;
+      // TODO: Make unid safe. See ModuleSourceFactory.safe().
       if(unid.length() < 1){
          workUnid = Globals.createUUID();
       }
-      Publication publication = Globals.getPublication();
-      File contentDirectory = publication.getContentDirectory();
-      File resourceDirectory = new File(contentDirectory, "resource" + File.separator + workUnid);
+      File resourceDirectory = new File(contentDirectory, workUnid);
       if(resourceDirectory.exists()){
          System.out.println("FlatResource.create: Resource creation failed because the Resource '" + workUnid + "' already exists." + resourceDirectory.getAbsolutePath());
          throw new ResourceException("Resource creation failed because the Resource '" + workUnid + "' already exists: " + resourceDirectory.getAbsolutePath());
@@ -494,7 +522,7 @@
       File resource = new File(resourceDirectory, FILENAME_RESOURCE);
       Document xml;
       try{
-         xml = DocumentHelper.createDocument("", "resource", null);
+         xml = DocumentHelper.createDocument("", FlatContent.DIRECTORY_CONTENT, null);
       }catch(DOMException e){
          System.out.println("CreateResource: DOMException");
          throw new ResourceException("CreateResource: DOMException", e);
@@ -509,10 +537,10 @@
       root.setAttribute("when", Globals.getDateString());
       String workType = type;
       int pos = type.lastIndexOf('/');
-      if(pos > 0)
-         workType = type.substring(pos + 1);
+      if(pos > 0) workType = type.substring(pos + 1);
       root.setAttribute("type", workType);
       root.setAttribute("doctype", workType);
+      if(isDesign) root.setAttribute(ATTR_DEFAULT_LANGUAGE, FlatDesign.DESIGN_LANGUAGE);
       // TODO: Throw these Exceptions.
       try{
          DocumentHelper.writeDocument(xml, resource);
@@ -527,8 +555,11 @@
          throw new ResourceException("CreateResource: IOException writing XML file: " + resource.getAbsolutePath(), ioe);
       }
       // Update Indexes
-      ((FlatContent) publication.getContent()).updateIndexes();
+      ((FlatContent) Globals.getPublication().getContent()).updateIndexes();
       // Return
       return new FlatResource(contentDirectory, workUnid);
    }
+   public boolean exists() {
+      return getTranslation().exists();
+   }
 }

Modified: lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatRevision.java
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatRevision.java?rev=693670&r1=693669&r2=693670&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatRevision.java (original)
+++ lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatRevision.java Tue Sep  9 17:30:20 2008
@@ -28,20 +28,16 @@
          metafile = new File(translationDirectory, revision + ".xml");
          resource = DocumentHelper.readDocument(metafile);
          root = resource.getDocumentElement();
-         if(root.hasAttribute("title"))
-            title = root.getAttribute("title");
-         if(root.hasAttribute("extension"))
-            extension = root.getAttribute("extension");
-         if(root.hasAttribute("href"))
-            href = root.getAttribute("href");
+         if(root.hasAttribute("title")) title = root.getAttribute("title");
+         if(root.hasAttribute("extension")) extension = root.getAttribute("extension");
+         if(root.hasAttribute("href")) href = root.getAttribute("href");
       }catch(javax.xml.parsers.ParserConfigurationException pce){
       }catch(org.xml.sax.SAXException saxe){
       }catch(java.io.IOException ioe){
       }
       if(extension.length() > 0){
          file = new File(translationDirectory, revision + "." + extension);
-      }else
-         file = metafile;
+      }else file = metafile;
    }
    public String getTitle() {
       return title;
@@ -53,7 +49,8 @@
       return href;
    }
    public String getURI() {
-      return file.getPath();
+      // System.out.println("FlatRevision.getURI=" + file.getAbsolutePath());
+      return file.getAbsolutePath();
    }
    public String getMetaURI() {
       return metafile.getPath();

Modified: lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatTranslation.java
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatTranslation.java?rev=693670&r1=693669&r2=693670&view=diff
==============================================================================
--- lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatTranslation.java (original)
+++ lenya/branches/revolution/1.3.x/src/java/org/apache/lenya/cms/content/flat/FlatTranslation.java Tue Sep  9 17:30:20 2008
@@ -1,7 +1,11 @@
 package org.apache.lenya.cms.content.flat;
 import java.io.File;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import org.apache.lenya.cms.content.Content;
 import org.apache.lenya.util.Globals;
 import org.apache.lenya.xml.DocumentHelper;
 import org.w3c.dom.Document;
@@ -12,54 +16,52 @@
  * @since 1.3
  */
 public class FlatTranslation {
-   File resourceDirectory;
-   File translationDirectory;
-   String language = "en";
-   String defaultLanguage = "en";
-   String live = "";
-   String edit = "last";
-   String revision = "live";
-   Document document;
-   Element root;
-   FlatRevision fr;
-   boolean initRevisions = false;
-   SortedSet revisions = new TreeSet();
-   boolean isChanged = false;
-   public FlatTranslation(File directory, String planguage, String prevision, String pdefaultLanguage) {
+   private File resourceDirectory;
+   private File translationDirectory;
+   private String language = "en";
+   private String defaultLanguage = "en";
+   private String revision = Content.REVISION_DEFAULT;
+   private Document document;
+   private Element root;
+   private FlatRevision flatRevision;
+   private boolean initRevisions = false;
+   private SortedSet revisions = new TreeSet(); // list of FlatRevisions' filenames without extension
+   private Map namedRevisions = new HashMap();
+   private boolean isChanged = false;
+   public FlatTranslation(File directory, String language, String revision, String defaultLanguage) {
+      // System.out.println("FlatTranslation new L=" + language + " DL=" + defaultLanguage + " REV=" + revision + " DIR=" + directory.getAbsolutePath());
       resourceDirectory = directory;
-      language = planguage;
-      defaultLanguage = pdefaultLanguage;
-      revision = prevision;
+      this.language = language;
+      this.defaultLanguage = defaultLanguage;
+      this.revision = revision;
       init();
    }
-   public FlatTranslation(File directory, String planguage, String prevision) {
+   public FlatTranslation(File directory, String language, String revision) {
+      // System.out.println("FlatTranslation new L=" + language + " REV=" + revision + " DIR=" + directory.getAbsolutePath());
       resourceDirectory = directory;
-      language = planguage;
-      revision = prevision;
-      defaultLanguage = planguage; // Set to publication's default
+      this.language = language;
+      this.revision = revision;
+      this.defaultLanguage = language; // Set to publication's default
       init();
    }
-   public FlatTranslation(File directory, String planguage) {
+   public FlatTranslation(File directory, String language) {
+      // System.out.println("FlatTranslation new L=" + language + " DIR=" + directory.getAbsolutePath());
       resourceDirectory = directory;
-      language = planguage;
-      defaultLanguage = planguage; // Set to publication's default
+      this.language = language;
+      this.defaultLanguage = language; // Set to publication's default
       init();
    }
    private void init() {
       translationDirectory = new File(resourceDirectory, language);
-      if(!translationDirectory.exists())
-         translationDirectory = new File(resourceDirectory, defaultLanguage);
-      if(!translationDirectory.exists())
-         return;
+      if(!translationDirectory.exists()) translationDirectory = new File(resourceDirectory, defaultLanguage);
+      if(!translationDirectory.exists()) return;
       File translationFile = new File(translationDirectory, "translation.xml");
       if(translationFile.exists()){
          try{
             document = DocumentHelper.readDocument(translationFile);
             root = document.getDocumentElement();
-            if(root.hasAttribute("live"))
-               live = root.getAttribute("live");
-            if(root.hasAttribute("edit"))
-               edit = root.getAttribute("edit");
+            if(root.hasAttribute(Content.REVISION_DEFAULT)) setNamedRevision(Content.REVISION_DEFAULT, root.getAttribute(Content.REVISION_DEFAULT));
+            if(root.hasAttribute("edit")) setNamedRevision("edit", root.getAttribute("edit"));
          }catch(javax.xml.parsers.ParserConfigurationException pce){
             System.out.println("FlatTranslation - ParserConfigurationException: " + translationFile.getAbsolutePath());
          }catch(org.xml.sax.SAXException saxe){
@@ -82,102 +84,143 @@
    public String[] getRevisions() {
       if(!initRevisions){
          String[] filelist = translationDirectory.list();
-         for(int f = 0; f < filelist.length; f++){
-            String filename = filelist[f];
-            int pos = filename.lastIndexOf(".");
-            if(pos > 0)
-               filename = filename.substring(0, pos);
-            if(!filename.equalsIgnoreCase("translation"))
-               revisions.add(filename);
+         if(null == filelist){
+            // System.out.println("FlatTranslatioOn.getRevisions NULL=" + translationDirectory.getAbsolutePath());
+         }else{
+            for(int f = 0; f < filelist.length; f++){
+               String filename = filelist[f];
+               int pos = filename.lastIndexOf(".");
+               if(pos > 0) filename = filename.substring(0, pos);
+               if(!filename.equalsIgnoreCase("translation")) revisions.add(filename);
+            }
+            initRevisions = true;
          }
-         initRevisions = true;
       }
       return (String[]) revisions.toArray(new String[0]);
    }
-   public String getLive() {
-      return live;
-   }
-   public String getEdit() {
-      return edit;
-   }
    public String getURI() {
-      if(null == fr)
-         fr = getRevision();
-      if(null == fr){
-         // System.out.println("FlatTranslation.getURI no revision.");
+      if(null == flatRevision) flatRevision = getRevision();
+      if(null == flatRevision){
+         // System.out.println("FlatTranslation.getURI: No revision.");
          return "";
       }
-      return fr.getURI();
+      return flatRevision.getURI();
    }
    public String getMetaURI() {
-      if(null == fr)
-         fr = getRevision();
-      if(null == fr)
-         return "";
-      return fr.getMetaURI();
+      if(null == flatRevision) flatRevision = getRevision();
+      if(null == flatRevision) return "";
+      return flatRevision.getMetaURI();
    }
    public String getNewURI() {
       String newRevision = Globals.getDateString();
       // WORK: Change Edit to newRevision
-      return new File(translationDirectory, newRevision + ".xml").getPath();
+      return (new File(translationDirectory, newRevision + ".xml")).getPath();
    }
    public String getExtension() {
-      if(null == fr)
-         fr = getRevision();
-      if(null == fr)
-         return "";
-      return fr.getExtension();
+      if(null == flatRevision) flatRevision = getRevision();
+      if(null == flatRevision) return "";
+      return flatRevision.getExtension();
    }
    public String getHREF() {
-      if(null == fr)
-         fr = getRevision();
-      if(null == fr)
-         return "";
-      return fr.getHREF();
+      if(null == flatRevision) flatRevision = getRevision();
+      if(null == flatRevision) return "";
+      return flatRevision.getHREF();
    }
    public FlatRevision getRevision() {
       return getRevision(revision);
    }
-   public FlatRevision getRevision(String prevision) {
-      String rev = prevision;
-      if(rev.equalsIgnoreCase("edit")){
-         if(edit.length() > 0){
-            rev = edit;
-         }else
-            rev = live;
+   public FlatRevision getRevision(String revision) {
+      // System.out.println("FlatTranslation.getRevision " + revision);
+      String rev = revision;
+      // Verify revisions is initialized.
+      getRevisions();
+      if(revisions.isEmpty()){
+         rev = Globals.getDateString();
+         initRevisions = false;
       }
-      if(rev.equalsIgnoreCase("live"))
-         rev = live;
+      if(rev.equalsIgnoreCase("edit")) rev = getNamedRevision("edit");
+      if(rev.equalsIgnoreCase(Content.REVISION_DEFAULT)) rev = getNamedRevision(Content.REVISION_DEFAULT);
       try{
-         if(rev.equalsIgnoreCase("last"))
-            rev = (String) revisions.last();
-         if(rev.equalsIgnoreCase("first"))
-            rev = (String) revisions.first();
+         if(rev.equalsIgnoreCase("last")) rev = (String) revisions.last();
+         if(rev.equalsIgnoreCase("first")) rev = (String) revisions.first();
       }catch(java.util.NoSuchElementException nsee){
          return null;
       }
-      if(null == rev)
+      // Defaults
+      // System.out.println("FlatTranslation.getRevision rev1=" + rev);
+      if(1 > rev.length()) rev = getNamedRevision(Content.REVISION_DEFAULT);
+      try{
+         if(1 > rev.length()) rev = (String) revisions.last();
+      }catch(java.util.NoSuchElementException nsee){
          return null;
-      if(rev.length() < 1)
+      }
+      if((null == rev) || (1 > rev.length())){
+         // System.out.println("FlatTranslation.getRevision rev=null");
          return null;
+      }
+      // System.out.println("FlatTranslation.getRevision revZ=" + rev);
       return new FlatRevision(translationDirectory, rev);
    }
+   void setNamedRevision(String name, String revision) {
+      namedRevisions.put(name, revision);
+      isChanged = true;
+   }
+   String getNamedRevision(String name) {
+      String revision = "";
+      if(namedRevisions.containsKey(name)){
+         revision = (String) namedRevisions.get(name);
+      }
+      if((1 > revision.length()) && namedRevisions.containsKey(Content.REVISION_DEFAULT)){
+         revision = (String) namedRevisions.get(Content.REVISION_DEFAULT);
+      }
+      if((1 > revision.length()) && namedRevisions.containsKey("last")) revision = (String) namedRevisions.get("last");
+      return revision;
+   }
+   /**
+    * @deprecated Use getNamedRevision(Content.REVISION_DEFAULT)
+    * @return
+    */
+   public String getLive() {
+      return getNamedRevision(Content.REVISION_DEFAULT);
+   }
+   /**
+    * @deprecated Use getNamedRevision("edit")
+    * @return
+    */
+   public String getEdit() {
+      return getNamedRevision("edit");
+   }
+   /**
+    * @deprecated Use setNamedRevision(Content.REVISION_DEFAULT, revision)
+    * @param revision
+    */
    void setLive(String revision) {
-      live = revision;
+      setNamedRevision(Content.REVISION_DEFAULT, revision);
       isChanged = true;
    }
+   /**
+    * @deprecated Use setNamedRevision("edit", revision)
+    * @param revision
+    */
    void setEdit(String revision) {
-      edit = revision;
+      setNamedRevision("edit", revision);
       isChanged = true;
    }
    void save() {
       if(isChanged){
+         FlatContent content = (FlatContent) Globals.getPublication().getContent();
          File file = new File(translationDirectory, "translation.xml");
-         /*
-          * Document doc; try{ doc = DocumentHelper.readDocument(file); }catch(javax.xml.parsers.ParserConfigurationException pce){ System.out.println("FlatTranslation.save - ParserConfigurationException:" + file.getAbsolutePath()); return; }catch(org.xml.sax.SAXException saxe){ System.out.println("FlatTranslation.save - SAXException:" + file.getAbsolutePath()); return; }catch(java.io.IOException ioe){ System.out.println("FlatTranslation.save - Could not read file:" + file.getAbsolutePath()); return; } root = doc.getDocumentElement();
-          */
-         root.setAttribute("live", live);
-         root.setAttribute("edit", edit);
+         // Used NamedRevisions
+         Iterator revisionNames = content.getRevisions().iterator();
+         while(revisionNames.hasNext()){
+            String revisionName = (String) revisionNames.next();
+            // TODO: NPE on setAttribute
+            // System.out.println("FlatTranslation.save - RevName:" + revisionName + " Rev:" + getNamedRevision(revisionName));
+            String revision = getNamedRevision(revisionName);
+            // if(0 < revision.length())
+            // Zero-length revision is valid for retracting (unpublishing).
+            root.setAttribute(revisionName, revision);
+         }
          try{
             // DocumentHelper.writeDocument(doc, file);
             DocumentHelper.writeDocument(document, file);
@@ -188,7 +231,8 @@
          }catch(java.io.IOException ioe2){
             System.out.println("FlatTranslation.save - Could not write file:" + file.getAbsolutePath());
          }
-         // TODO: Update indexes for this language.
+         // TODO: Update indexes for just this language.
+         content.updateIndexes();
       }
       isChanged = false;
    }
@@ -201,9 +245,11 @@
          file.delete();
          if(extension.length() > 0){
             file = new File(translationDirectory, revision + "." + extension);
-            if(file.exists())
-               file.delete();
+            if(file.exists()) file.delete();
          }
       }
    }
+   public boolean exists() {
+      return getRevision().exists();
+   }
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.