Update of
/var/cvs/contributions/CMSContainer/cmsc/contentrepository/src/java/com/finalist/cmsc/repository
In directory james.mmbase.org:/tmp/cvs-serv12645
Modified Files:
RepositoryUtil.java
Log Message:
CMSC-1298 Clone channel feature strip the nodes that not in the current
channel tree
See also:
http://cvs.mmbase.org/viewcvs/contributions/CMSContainer/cmsc/contentrepository/src/java/com/finalist/cmsc/repository
See also: http://www.mmbase.org/jira/browse/CMSC-1298
Index: RepositoryUtil.java
===================================================================
RCS file:
/var/cvs/contributions/CMSContainer/cmsc/contentrepository/src/java/com/finalist/cmsc/repository/RepositoryUtil.java,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -b -r1.35 -r1.36
--- RepositoryUtil.java 23 Feb 2009 08:40:41 -0000 1.35
+++ RepositoryUtil.java 24 Feb 2009 10:36:27 -0000 1.36
@@ -35,12 +35,15 @@
import org.mmbase.bridge.RelationManager;
import org.mmbase.bridge.util.Queries;
import org.mmbase.bridge.util.SearchUtil;
+import org.mmbase.datatypes.DataType;
import org.mmbase.storage.search.FieldValueDateConstraint;
import org.mmbase.storage.search.StepField;
import org.mmbase.storage.search.implementation.BasicFieldValueConstraint;
import org.mmbase.storage.search.implementation.BasicFieldValueDateConstraint;
import org.mmbase.util.logging.Logger;
import org.mmbase.util.logging.Logging;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
import com.finalist.cmsc.mmbase.PropertiesUtil;
import com.finalist.cmsc.mmbase.RelationUtil;
@@ -49,9 +52,14 @@
import com.finalist.cmsc.security.SecurityUtil;
import com.finalist.cmsc.security.UserRole;
import com.finalist.cmsc.security.forms.RolesInfo;
+import com.finalist.cmsc.util.XmlUtil;
public final class RepositoryUtil {
+ private static final String RELATION_ID = "relationID";
+
+ private static final String DESTINATION_LOWER = "destination";
+
public static final String NAME_FIELD = "name";
/** MMbase logging system */
@@ -1361,7 +1369,11 @@
contentChannels.add(0, getRootNode(cloud));
return contentChannels;
}
-
+ /** Remove a asset element from a channel
+ *
+ * @param asset
+ * @param channelNode
+ */
public static void removeAssetFromChannel(Node asset, Node channelNode) {
RepositoryUtil.addDeletionRelation(asset, channelNode);
}
@@ -1379,8 +1391,16 @@
}
return query.getNodeManager().getList(query);
}
+ /**
+ * Clone nodes related with a node or channel
+ * @param sourceNode source channel
+ * @param destNode destination node
+ * @param copiedNodes map used for the mapping number-pair
+ * @param output
+ * @param channels the current channel tree list
+ */
public static void cloneRelatedNodes(Node sourceNode,Node
destNode,Map<Integer, Integer> copiedNodes ,StringBuilder output,List<Integer>
channels) {
- List<Relation> relations = sourceNode.getRelations(null, null,
"destination");
+ List<Relation> relations = sourceNode.getRelations(null, null,
DESTINATION_LOWER);
for (Relation rel : relations) {
if(rel == null) {
@@ -1429,7 +1449,7 @@
//Only clone node, when it hasn't been cloned before.
Node destChild;
if (copiedNodes.get(sourceChild.getNumber()) == null) {
- destChild = cloneNode(sourceChild);
+ destChild = cloneNode(sourceChild,copiedNodes,channels);
copiedNodes.put(Integer.valueOf(sourceChild.getNumber()),Integer.valueOf(destChild.getNumber()));
cloned = true;
//Logging
@@ -1478,7 +1498,14 @@
}
}
}
- public static Node cloneNode(Node localNode) {
+ /**
+ * Clone a node
+ * @param localNode
+ * @param copiedNodes number-pairs
+ * @param channels
+ * @return
+ */
+ public static Node cloneNode(Node localNode,Map<Integer, Integer>
copiedNodes,List<Integer> channels) {
if (isRelation(localNode)) {
return CloneUtil.cloneRelation(localNode);
}
@@ -1496,7 +1523,7 @@
if (!(fieldName.equals("owner") || fieldName.equals("number") ||
fieldName.equals("otype") ||
(fieldName.indexOf("_") == 0))) {
- cloneNodeField(localNode, newNode, field);
+ cloneNodeField(localNode, newNode,
field,copiedNodes,channels);
}
}
}
@@ -1516,18 +1543,220 @@
* @param field
* the field to clone
*/
- public static void cloneNodeField(Node sourceNode, Node destinationNode,
Field field) {
+ public static void cloneNodeField(Node sourceNode, Node destinationNode,
Field field,Map<Integer, Integer> copiedNodes,List<Integer> channels) {
String fieldName = field.getName();
if (destinationNode.getNodeManager().hasField(fieldName) == true) {
Field sourceField = sourceNode.getNodeManager().getField(fieldName);
if (sourceField.getState() != Field.STATE_SYSTEM &&
!sourceField.isVirtual()) {
destinationNode.setValueWithoutProcess(fieldName,
- sourceNode.getValueWithoutProcess(fieldName));
+ strip(sourceNode,field,copiedNodes,channels));
+ }
+ }
+ }
+
+ /**
+ * To strip the Node in richtext and that not in the current channel tree
+ * @param sourceNode
+ * @param field
+ * @param copiedNodes
+ * @param channels
+ * @return
+ */
+ public static Object strip(Node sourceNode,Field field,Map<Integer,
Integer> copiedNodes,List<Integer> channels) {
+ DataType dataType = field.getDataType();
+ while (StringUtils.isEmpty(dataType.getName())) {
+ dataType = dataType.getOrigin();
+ }
+ if ("cmscrichtext".equals(dataType.getName())) {
+ String fieldname = field.getName();
+ String fieldValue = (String)
sourceNode.getValueWithoutProcess(fieldname);
+ log.debug("richtext field: " + fieldname.trim());
+ // htmlFields.add(fieldname);
+ if (StringUtils.isNotEmpty(fieldValue)) {
+ try {
+ if (hasRichtextItems(fieldValue)) {
+ Document doc = getRichTextDocument(new
GetRichTextDocumentParameter(fieldValue));
+ resolveResources(sourceNode,doc,copiedNodes,channels);
+ String out = getRichTextString(doc);
+ out = fixEmptyAnchors(out);
+ log.debug("final richtext text = " + out);
+ return out;
+ }
+ }
+ catch (Exception e) {
+ log.error("An error occured while resolving inline resources!",
e);
+ }
+ }
+ }
+ return sourceNode.getValueWithoutProcess(field.getName());
+ }
+ public static String fixEmptyAnchors(String xmlStr) {
+ String xml = "";
+ int begin = 0;
+ int end = 0;
+ while ((begin = nextResult(xmlStr, "<a ", end)) > -1) {
+ xml += xmlStr.substring(end, begin);
+
+ int gt = xmlStr.indexOf('>', begin);
+ int closinggt = xmlStr.indexOf("/>", begin);
+ boolean emptyTag = closinggt != -1 && gt >= closinggt + 1;
+ if (emptyTag) {
+ end = closinggt;
+ xml += xmlStr.substring(begin, end) + "></a>";
+ end += 2;
+ }
+ else {
+ end = gt + 1;
+ xml += xmlStr.substring(begin, end);
+ }
+ }
+ if (end < xmlStr.length()) {
+ xml += xmlStr.substring(end);
+ }
+ return xml;
+ }
+ private static int nextResult(String xmlStr, String substr, int from) {
+ String upXmlStr = xmlStr.toLowerCase();
+ String upSubstr = substr.toLowerCase();
+
+ xmlStr.indexOf(upSubstr, from);
+
+ return upXmlStr.indexOf(upSubstr, from);
}
+ public final static String getRichTextString(Document doc) {
+ // to string and strip root node, doctype and xmldeclaration
+ String out = XmlUtil.serializeDocument(doc, false, false, true, true);
+ out = out.replaceAll("<.?richtext.?>", "");
+ out = XmlUtil.unescapeXMLEntities(out);
+ return out;
}
+
+
+ public final static Document
getRichTextDocument(GetRichTextDocumentParameter parameterObject) {
+ String out = XmlUtil.escapeXMLEntities(parameterObject.in);
+ out = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<richtext>" +
out + "</richtext>";
+ Document doc = XmlUtil.toDocument(out, false);
+ return doc;
+ }
+ public static void resolveResources(Node node,Document doc,Map<Integer,
Integer> copiedNodes,List<Integer> channels) {
+ resolveLinks(doc, node,copiedNodes,channels);
+ resolveImages(doc, node,copiedNodes,channels);
+ }
+ public final static boolean hasRichtextItems(String in) {
+ return (in.indexOf("<a") > -1 || in.indexOf("<img") > -1);
+ }
+ /**
+ * To resolve the links in Richtext fields
+ * @param doc
+ * @param sourceNode
+ * @param copiedNodes
+ * @param channels
+ */
+ public static void resolveLinks(Document doc, Node sourceNode,Map<Integer,
Integer> copiedNodes,List<Integer> channels) {
+ if (doc == null) {
+ return;
+ }
+ // collect <A> tags
+ org.w3c.dom.NodeList nl = doc.getElementsByTagName("a");
+ log.debug("number of links: " + nl.getLength());
+
+ for (int i = 0, len = nl.getLength(); i < len; i++) {
+ Element link = (Element) nl.item(i);
+
+ if (link.hasAttribute(DESTINATION_LOWER)
+ &&
"undefined".equalsIgnoreCase(link.getAttribute(DESTINATION_LOWER))) {
+ link.removeAttribute(DESTINATION_LOWER);
+ }
+ if (link.hasAttribute(RELATION_ID)
+ &&
"undefined".equalsIgnoreCase(link.getAttribute(RELATION_ID))) {
+ link.removeAttribute(RELATION_ID);
+ }
+ // handle relations to other objects
+ if (isInlineAttributesComplete(link)) {
+ // get id of the link
+ //String id = link.getAttribute("relationID");
+ int source =
Integer.parseInt(link.getAttribute(DESTINATION_LOWER));
+ org.w3c.dom.Node parentNode = link.getParentNode();
+ if (source > 0) {
+ Node node = sourceNode.getCloud().getNode(source);
+ if (!isRelatedWithCurrentChannelTree(node, channels)) {
+ Element newNode = doc.createElement("span");
+ newNode.appendChild(link.getFirstChild());
+ parentNode.replaceChild(newNode,link);
+ }
+ else {
+ Integer destination = copiedNodes.get(source);
+ if (destination != null && destination > 0 &&
sourceNode.getCloud().hasNode(destination)) {
+ Relation rel = RelationUtil.createRelation(sourceNode,
sourceNode.getCloud().getNode(destination), "inlinerel");
+ link.setAttribute(DESTINATION_LOWER,
String.valueOf(destination));
+ link.setAttribute(RELATION_ID,
String.valueOf(rel.getNumber()));
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ public static boolean isNewInline(Element element) {
+ return element.hasAttribute(DESTINATION_LOWER) &&
!element.hasAttribute(RELATION_ID);
}
+
+ public static boolean isInlineAttributesComplete(Element element) {
+ return element.hasAttribute(DESTINATION_LOWER) &&
element.hasAttribute(RELATION_ID);
+ }
+ /**
+ * To resolve the images used in the richtext fileds
+ * @param doc
+ * @param sourceNode
+ * @param copiedNodes
+ * @param channels
+ */
+ public static void resolveImages(Document doc,Node sourceNode,Map<Integer,
Integer> copiedNodes,List<Integer> channels) {
+ if (doc == null) {
+ return;
+ }
+ org.w3c.dom.NodeList nl = doc.getElementsByTagName("img");
+ log.debug("number of images: " + nl.getLength());
+ for (int i = 0, len = nl.getLength(); i < len; i++) {
+ Element image = (Element) nl.item(i);
+
+ if (image.hasAttribute(DESTINATION_LOWER)
+ &&
"undefined".equalsIgnoreCase(image.getAttribute(DESTINATION_LOWER))) {
+ image.removeAttribute(DESTINATION_LOWER);
+ }
+ if (image.hasAttribute(RELATION_ID)
+ &&
"undefined".equalsIgnoreCase(image.getAttribute(RELATION_ID))) {
+ image.removeAttribute(RELATION_ID);
+ }
+
+ if (isInlineAttributesComplete(image)) {
+ // get id of the image
+ int source =
Integer.parseInt(image.getAttribute(DESTINATION_LOWER));
+
+ org.w3c.dom.Node parentNode = image.getParentNode();
+ // parentNode.removeChild(image);
+ // MMObjectNode imagerel = getImageInlineRel(id);
+ if (source > 0 ) {
+ Node node = sourceNode.getCloud().getNode(source);
+ if (!isRelatedWithCurrentChannelTree(node, channels)) {
+ parentNode.removeChild(image);
+ }
+ else {
+ Integer destination = copiedNodes.get(source);
+ if (destination != null && destination > 0 &&
sourceNode.getCloud().hasNode(destination)) {
+ Relation rel = RelationUtil.createRelation(sourceNode,
sourceNode.getCloud().getNode(destination), "imageinlinerel");
+ image.setAttribute(DESTINATION_LOWER,
String.valueOf(destination));
+ image.setAttribute(RELATION_ID,
String.valueOf(rel.getNumber()));
+ }
+ }
+ }
+ }
+
+ }
+ }
/**
* quick test to see if node is a relation by testing fieldnames
* @param node Possible relation
_______________________________________________
Cvs mailing list
[email protected]
http://lists.mmbase.org/mailman/listinfo/cvs