gianugo 2003/07/28 04:28:22
Modified: src/java/org/apache/cocoon/transformation
SourceWritingTransformer.java
src/documentation/xdocs/userdocs/transformers
sourcewriting-transformer.xml
. status.xml
Log:
Added delete capabilities to the SourceWritingTransformer, while solving
a DOM bug(?) with new documents creation.
Revision Changes Path
1.5 +77 -9
cocoon-2.1/src/java/org/apache/cocoon/transformation/SourceWritingTransformer.java
Index: SourceWritingTransformer.java
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/java/org/apache/cocoon/transformation/SourceWritingTransformer.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- SourceWritingTransformer.java 16 Mar 2003 17:49:15 -0000 1.4
+++ SourceWritingTransformer.java 28 Jul 2003 11:28:20 -0000 1.5
@@ -110,6 +110,12 @@
* <source:reinsert>[Optional] The XPath (relative to
<source:replace/>) to backup the overwritten node
to</source:reinsert> - eg: "foo/versions" or "/doc/versions/foo". NOTE:
If specified and a node is replaced, all children of this replaced node will be
reinserted at the given path.
* <source:fragment>The XML Fragment to be
written</source:fragment> - eg: "<foo><bar
id="dogcow"/></foo>" or
"<foo/><bar><dogcow/><bar/>" etc.
* <source:insert>
+ *
+ * <source:delete > - deletes an existing asset.
+ * <source:source>The System ID of the asset to be
deleted</source:source> - eg: "docs/blah.xml" or "context://blah.xml" etc.
+ * <source:path>[Ignored] XPath to specify how your content is
wrapped</source:path>
+ * <source:fragment>[Ignored]The XML Fragment to be
written</source:fragment>
+ * <source:delete>
* </pre>
*
*
@@ -248,6 +254,7 @@
*
* @author <a href="mailto:[EMAIL PROTECTED]">Carsten Ziegeler</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Jeremy Quinn</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Gianugo Rabellino</a>
* @version CVS $Id$
*/
public class SourceWritingTransformer
@@ -262,6 +269,7 @@
public static final String PATH_ELEMENT = "path";
public static final String FRAGMENT_ELEMENT = "fragment";
public static final String REPLACE_ELEMENT = "replace";
+ public static final String DELETE_ELEMENT = "delete";
public static final String SOURCE_ELEMENT = "source";
public static final String REINSERT_ELEMENT = "reinsert";
/** outgoing elements */
@@ -281,6 +289,7 @@
public static final String ACTION_NONE = "none";
public static final String ACTION_NEW = "new";
public static final String ACTION_OVER = "overwritten";
+ public static final String ACTION_DELETE = "deleted";
/** The current state */
private static final int STATE_OUTSIDE = 0;
private static final int STATE_INSERT = 1;
@@ -290,6 +299,7 @@
private static final int STATE_FILE = 6;
private static final int STATE_REINSERT = 7;
private static final int STATE_WRITE = 8;
+ private static final int STATE_DELETE = 9;
private int state;
private int parent_state;
@@ -366,15 +376,20 @@
this.stack.push(attr.getValue(SERIALIZER_ATTRIBUTE));
this.stack.push("END");
+ // Element: delete
+ } else if (this.state == STATE_OUTSIDE &&
name.equals(DELETE_ELEMENT)) {
+ this.state = STATE_DELETE;
+ this.parent_state = state;
+ this.stack.push("END");
// Element: file
} else if (name.equals(SOURCE_ELEMENT)
- && (this.state == STATE_INSERT || this.state ==
STATE_WRITE)) {
+ && (this.state == STATE_INSERT || this.state ==
STATE_WRITE || this.state == STATE_DELETE)) {
this.state = STATE_FILE;
this.startTextRecording();
// Element: path
} else if (name.equals(PATH_ELEMENT)
- && (this.state == STATE_INSERT || this.state ==
STATE_WRITE)) {
+ && (this.state == STATE_INSERT || this.state ==
STATE_WRITE || this.state == STATE_DELETE)) {
this.state = STATE_PATH;
this.startTextRecording();
@@ -386,7 +401,7 @@
// Element: fragment
} else if (name.equals(FRAGMENT_ELEMENT)
- && (this.state == STATE_INSERT || this.state ==
STATE_WRITE)) {
+ && (this.state == STATE_INSERT || this.state ==
STATE_WRITE || this.state == STATE_DELETE)) {
this.state = STATE_FRAGMENT;
this.startRecording();
@@ -466,6 +481,22 @@
this.state = STATE_OUTSIDE;
+ // Element: delete
+ } else if (name.equals(DELETE_ELEMENT) && this.state ==
STATE_DELETE) {
+ String sourceName = null;
+ String tag;
+ do {
+ tag = (String)this.stack.pop();
+ if (tag.equals("FILE")) {
+ sourceName = (String)this.stack.pop();
+ } else if (tag.equals("FRAGMENT")) {
+ //Get rid of it
+ this.stack.pop();
+ }
+ } while ( !tag.equals("END"));
+
+ this.deleteSource(sourceName);
+ this.state = STATE_OUTSIDE;
// Element: file
} else if (name.equals(SOURCE_ELEMENT) == true && this.state ==
STATE_FILE) {
this.state = this.parent_state;
@@ -506,6 +537,34 @@
}
}
+ /**
+ * Deletes a source
+ * @param sourceName
+ */
+ private void deleteSource(String systemID) throws ProcessingException,
IOException, SAXException {
+ try {
+ Source source = resolver.resolveURI(systemID);
+ if ( ! (source instanceof ModifiableSource)) {
+ throw new ProcessingException("Source '"+systemID+"' is not
writeable.");
+ }
+ ModifiableSource ms = (ModifiableSource)source;
+ ms.delete();
+ } catch (SourceException se) {
+ reportResult("none",
+ "delete",
+ "unable to delete Source:" + se.getMessage(),
+ systemID,
+ RESULT_FAILED,
+ ACTION_DELETE);
+ }
+ reportResult("none",
+ "delete",
+ "source deleted successfully",
+ systemID,
+ RESULT_SUCCESS,
+ ACTION_DELETE);
+ }
+
public void recycle() {
super.recycle();
}
@@ -647,7 +706,7 @@
// import the fragment
Node importNode = resource.importNode(fragment, true);
if ( path.equals("") ) { // this is allowed in write
- resource.appendChild(importNode);
+ resource.appendChild(importNode.getFirstChild());
message = "entire source overwritten";
} else {
@@ -730,6 +789,19 @@
String action = ACTION_NONE;
if (!failed) { action = (exists) ? ACTION_OVER : ACTION_NEW; }
+ this.reportResult(localSerializer, tagname, message, target, result,
action);
+
+ if (this.getLogger().isDebugEnabled() == true) {
+ this.getLogger().debug("END insertFragment");
+ }
+ }
+
+ private void reportResult(String localSerializer,
+ String tagname,
+ String message,
+ String target,
+ String result,
+ String action) throws SAXException {
sendStartElementEvent(RESULT_ELEMENT);
sendStartElementEvent(EXECUTION_ELEMENT);
sendTextEvent(result);
@@ -752,10 +824,6 @@
sendEndElementEvent(SERIALIZER_ELEMENT);
}
sendEndElementEvent(RESULT_ELEMENT);
-
- if (this.getLogger().isDebugEnabled() == true) {
- this.getLogger().debug("END insertFragment");
- }
}
1.2 +38 -2
cocoon-2.1/src/documentation/xdocs/userdocs/transformers/sourcewriting-transformer.xml
Index: sourcewriting-transformer.xml
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/documentation/xdocs/userdocs/transformers/sourcewriting-transformer.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- sourcewriting-transformer.xml 9 Mar 2003 00:08:27 -0000 1.1
+++ sourcewriting-transformer.xml 28 Jul 2003 11:28:22 -0000 1.2
@@ -13,7 +13,8 @@
</header>
<body>
<s1 title="Source Writing Transformer">
- <p>Diverts xml from a pipeline, writing it to a
Source.</p>
+ <p>Diverts xml from a pipeline, writing it to a Source
(or
+ deleting it).</p>
<p>Thankfully, <code>FileSource</code> is no longer the
only <code>Source</code> that currently implements <code>WritableSource</code>;
there are implementations of WebDAV and Apache Slide WritableSources in the
scratchpad. Hopefully further <code>ModifiableSource</code> implementations
(XMLDB, CVS, Email, SQL, etc.) will be appear in the future.</p>
<ul>
<li>Name : write-source</li>
@@ -39,10 +40,21 @@
[<source:replace/>]
[<source:reinsert/>]
</source:insert>
+
+ <source:delete/>
+ <source:source/>
+ [<source:path/>] - Ignored
+ [<source:fragment/>] - Ignored
+ [<source:replace/>] - Ignored
+ [<source:reinsert/>] - Ignored
+ </source:insert>
]]>
</source>
<p>In the namespace
<code>xmlns:source="http://apache.org/cocoon/source/1.0"</code>.</p>
- <p>The contents of the
<code><![CDATA[<source:fragment/>]]></code> tag are written to the specified
ModifiableSource when the document containing it is transformed by
SourceWritingTransformer.</p>
+ <p>The contents of the
<code><![CDATA[<source:fragment/>]]></code>
+ tag are written to the specified ModifiableSource when the
+ document containing it is transformed by SourceWritingTransformer
+ (or deleted if you are using the <code>delete </code>instruction).</p>
</s1>
<s1 title="Definition">
<source>
@@ -170,6 +182,16 @@
<li>if 'reinsert' is specified
and it does not exist, no action occurs.</li>
</ul>
</s2>
+ <s2 title="source:delete">
+ <p>This instruction takes only a
<code><![CDATA[<source:source/>]]></code>
+ parameter (as a child tag) and deletes the corresponding
+ source. All other <code>source:*</code> tags are ignored, if
+ present: this allows for easy source-write instructions to be
+ generated on the fly (e.g. by a stylesheet). Just change
+ <code>source:write</code> to <code>source:delete</code> and
+ you're set.
+ </p>
+ </s2>
</s1>
<s1 title="Examples">
@@ -251,6 +273,20 @@
<p>This sample does not currently work,
see the tests in the scratchpad at
<code>http://localhost:8080/cocoon/mount/editor/tests</code>.</p>
<note>You must have built Cocoon with
the scratchpad included for this link to work.</note>
</s2>
+ <s2 title="Delete a source">
+ <source>
+ <![CDATA[
+ <page>
+ ...
+ <source:delete>
+ <source:source>context://doc/editable/my.xml</source:source>
+ <source:delete>
+ ...
+ </page>
+ ]]>
+ </source>
+
+ </s2>
<s2 title="Sample of the output of these tags">
<p>This is the kind of information that the
<code>SourceWritingTransformer</code> outputs to the pipeline, replacing the
original <code>source:write</code> and <code>source:insert</code> tags</p>
<source>
1.96 +14 -1 cocoon-2.1/status.xml
Index: status.xml
===================================================================
RCS file: /home/cvs/cocoon-2.1/status.xml,v
retrieving revision 1.95
retrieving revision 1.96
diff -u -r1.95 -r1.96
--- status.xml 20 Jul 2003 03:33:42 -0000 1.95
+++ status.xml 28 Jul 2003 11:28:22 -0000 1.96
@@ -189,6 +189,19 @@
<changes>
<release version="@version@" date="@date@">
+ <action dev="GR" type="add">
+ Added delete capabilities to the SourceWritingTransformer.
+ </action>
+ <action dev="GR" type="add" fixes-bug="21881" due-to="Guido Casper"
+ due-to-email="[EMAIL PROTECTED]">
+ Add a defaultContentType parameter to StreamGenerator, to comply
+ with misbehaving clients.
+ </action>
+ <action dev="GR" type="add" fixes-bug="21778" due-to="Guido Casper"
+ due-to-email="[EMAIL PROTECTED]">
+ Add a new set of WebDAV samples, with the capability of serving
+ WebDAV content straight from Cocoon.
+ </action>
<action dev="DC" type="fix" fixes-bug="21557" due-to="Conal Tuohy"
due-to-email="[EMAIL PROTECTED]">
Various fixes and enhancements to Lucene search. Propagate the lucene:*
elements to the result tree and add "elapsed-time" attribute, so now