001: package com.teamkonzept.webman.field;
002:
003: import com.teamkonzept.webman.mainint.*;
004: import com.teamkonzept.webman.mainint.db.queries.content.SelectGroupContentChilds; //import com.teamkonzept.webman.mainint.events.CEEventHandler;
005: // import com.teamkonzept.webman.mainint.events.contentedit.CEUtils;
006:
007: import com.teamkonzept.lib.*;
008: import com.teamkonzept.publishing.markups.*;
009: import com.teamkonzept.web.*;
010: import com.teamkonzept.field.db.queries.*;
011: import com.teamkonzept.field.db.*;
012: import com.teamkonzept.db.*;
013: import com.teamkonzept.field.*;
014: import de.webman.generator.*;
015: import de.webman.content.workflow.*;
016: import java.sql.*;
017: import java.util.*;
018: import com.teamkonzept.international.LanguageManager;
019: import org.w3c.dom.*;
020: import org.apache.log4j.Category;
021: import de.webman.content.Content;
022: import de.webman.content.workflow.ContentVersion;
023: import de.webman.util.log4j.WebmanCategory;
024:
025: /**
026: * The content reference field control.
027: *
028: * @author $Author: uli $
029: * @version $Revision: 1.57 $
030: */
031: public class TKContentReferenceField extends TKAtomField {
032:
033: /**
034: * The logging category.
035: */
036: private static WebmanCategory cat = (WebmanCategory) WebmanCategory
037: .getInstance(TKContentReferenceField.class);
038:
039: /**
040: * The class identifier.
041: */
042: public static final String CLASS_ID = "CONTENTREF";
043:
044: /**
045: * key for nodes
046: **/
047: public static final String NODE_KEY = "NODE";
048:
049: /**
050: * key for multiple key
051: **/
052: public static final String MULTIPLE_KEY = "MULTIPLE";
053:
054: /** Key fuer nur Namen holen */
055: public static final String NAME_ONLY_KEY = "NAME_ONLY";
056:
057: public static final String YES_VALUE = "YES";
058: public static final String NO_VALUE = "NO";
059:
060: protected int contentNodeId;
061: protected boolean multipleSelection;
062: protected boolean deliverOnlyNames;
063:
064: /**
065: * Creates an empty content reference field control.
066: */
067: public TKContentReferenceField() {
068: super ();
069: }
070:
071: public TKContentReferenceField(String name, int contentNodeId) {
072: this (name, contentNodeId, null);
073: }
074:
075: public TKContentReferenceField(String name, int contentNodeId,
076: String showName) {
077: this (name, contentNodeId, true, showName);
078: }
079:
080: public TKContentReferenceField(String name, int contentNodeId,
081: boolean deliverOnlyNames, String showName) {
082: this (name, contentNodeId, deliverOnlyNames, false, showName);
083: }
084:
085: public TKContentReferenceField(String name, int contentNodeId,
086: boolean deliverOnlyNames, boolean multipeSelection,
087: String showName) {
088: initContentReferenceField(CLASS_ID, name, contentNodeId,
089: deliverOnlyNames, multipeSelection, showName);
090: }
091:
092: /**
093: * tja, irgendne intitialisierung halt oder?
094: * @param type ...
095: * @param name ...
096: * @param contentNodeId ...
097: * @param deliverOnlyNames ...
098: * @param multipleSelection ...
099: * @param showName ...
100: **/
101: public final void initContentReferenceField(String type,
102: String name, int contentNodeId, boolean deliverOnlyNames,
103: boolean multipleSelection, String showName) {
104: initAtomField(type, name, showName);
105: this .contentNodeId = contentNodeId;
106: this .deliverOnlyNames = deliverOnlyNames;
107: this .multipleSelection = multipleSelection;
108: }
109:
110: /**
111: * Methode zur Definition eines Eingabefeldes
112: */
113: public TKFieldGroup getDefGroup(TKFieldSwitch allSwitch,
114: TKFieldSwitchList allSwitchList) {
115:
116: TKVector multipleOptions = new TKVector(2);
117: multipleOptions
118: .addElement(new TKOptionFieldEntry(LanguageManager
119: .getText(LanguageManager.GENERAL, "YES"),
120: YES_VALUE));
121: multipleOptions.addElement(new TKOptionFieldEntry(
122: LanguageManager.getText(LanguageManager.GENERAL, "NO"),
123: NO_VALUE));
124:
125: TKBaseField[] inputArray = {
126: new TKInputField(NAME_KEY,
127: TKContentSiteReferenceField.WIDTH_ONE,
128: TKContentSiteReferenceField.WIDTH_TWO,
129: LanguageManager.getText(LANGUAGE_CONTEXT,
130: "CONTENT_REF_NAME"),
131: TKInputField.CHECK_STRING),
132: new TKInputField(SHOW_NAME_KEY,
133: TKContentSiteReferenceField.WIDTH_THREE,
134: TKContentSiteReferenceField.WIDTH_FOUR,
135: LanguageManager.getText(LANGUAGE_CONTEXT,
136: "CONTENT_REF_SHOWNAME"),
137: TKInputField.CHECK_STRING),
138: //new TKInputField( NODE_KEY, 7, 7, "NodeID des Gruppenknotens" ),
139: new TKContentNodeTypeSelectorField(NODE_KEY,
140: LanguageManager.getText(LANGUAGE_CONTEXT,
141: "CONTENT_REF_NODE"),
142: TKContentNodeTypeSelectorField.GROUP_NODE_TYPE),
143: new TKCheckField(MULTIPLE_KEY, LanguageManager.getText(
144: LANGUAGE_CONTEXT, "CONTENT_REF_MULTIPLE"),
145: multipleOptions, false),
146: new TKCheckField(NAME_ONLY_KEY, LanguageManager
147: .getText(LANGUAGE_CONTEXT,
148: "CONTENT_REF_NAME_ONLY"),
149: multipleOptions, false) };
150: TKFieldGroup inputGroup = new TKFieldGroup(
151: TKContentReferenceField.CLASS_ID, new TKVector(
152: inputArray), LanguageManager.getText(
153: LANGUAGE_CONTEXT,
154: TKContentReferenceField.CLASS_ID));
155:
156: return inputGroup;
157: }
158:
159: /**
160: initialisiert das feld basierend auf den daten, die die feldgruppe von getDefGroup zurueckliefert
161: */
162: public void init(String classId, Object initData)
163: throws TKUnregisteredClassException,
164: ClassNotFoundException, InstantiationException,
165: IllegalAccessException {
166: super .init(classId, initData);
167: TKHashtable data = (TKHashtable) initData;
168: contentNodeId = Integer.parseInt((String) data.get(NODE_KEY));
169: multipleSelection = ((String) data.get(MULTIPLE_KEY))
170: .equals(YES_VALUE);
171: deliverOnlyNames = ((String) data.get(NAME_ONLY_KEY))
172: .equals(YES_VALUE);
173: }
174:
175: /**
176: * Returns the internal representation of this field.
177: *
178: * @return the internal representation of this field.
179: */
180: public Object toData() {
181: TKHashtable result = (TKHashtable) super .toData();
182: result.put(NODE_KEY, String.valueOf(contentNodeId));
183: result.put(MULTIPLE_KEY, (multipleSelection ? YES_VALUE
184: : NO_VALUE));
185: result.put(NAME_ONLY_KEY, (deliverOnlyNames ? YES_VALUE
186: : NO_VALUE));
187: return result;
188: }
189:
190: /**
191: * Fills the data held by this field into the specified template.
192: *
193: * @param template the template.
194: * @param value a value ?
195: * @param prefix a prefix ?
196: */
197: public void fillIntoTemplate(TKHTMLTemplate template, Object value,
198: String prefix) {
199: try {
200: super .fillIntoTemplate(template, value, prefix);
201: template.set(NODE_KEY, String.valueOf(this .contentNodeId));
202:
203: if (this .multipleSelection) {
204: template.set(MULTIPLE_KEY, Boolean.TRUE);
205: }
206:
207: // Initialize workflow.
208: VersionStatics statics = VersionStatics.setup();
209: TKHashtable statusPool = VersionStatus.selectSingles(
210: statics, false);
211: TKHashtable filter = VersionSelection
212: .initContentFilter(statusPool);
213: TKVector filteredInstances = new TKVector();
214:
215: // Get all instances.
216: TKVector allInstances = VersionCache.getVersionInfo(
217: new Integer(this .contentNodeId), false);
218:
219: for (int i = 0; i < allInstances.size(); i++) {
220: // Apply filter.
221: Content content = (Content) allInstances.elementAt(i);
222:
223: if (content.filterTransitions(filter, "SRC")) {
224: TKHashtable entry = new TKHashtable();
225: entry.put("CONTENT_NODE_SHORTNAME", content
226: .getShortName());
227: entry.put("CONTENT_NODE_NAME", content.getName());
228:
229: filteredInstances.addElement(entry);
230: }
231: }
232:
233: // Publish list to template.
234: template.setListIterator(new TKStandardPluginIterator(
235: prefix + getName(), null, filteredInstances, false,
236: template.getListIterator()));
237: } catch (Exception e) {
238: cat.error(e);
239: }
240: }
241:
242: /**
243: * fuehrt die eigentliche Ermittlung der ContentReferenzen bei der Generierung durch
244: * @param data entweder einzelner Shortname oder Liste von Namen
245: * @param context der Generierungscontext
246: */
247: public TKVector getSelectedContents(Object data,
248: GeneratorContext context) {
249: if (data == null)
250: return new TKVector();
251: TKVector searchNames;
252: if (data instanceof TKVector) {
253: searchNames = (TKVector) data;
254: } else {
255: searchNames = new TKVector(1);
256: searchNames.addElement(data);
257: }
258:
259: cat.debug("Got selected contents : " + searchNames);
260: TKVector contentNodes = new TKVector();
261:
262: SiteContentNode node = context.contentNodes
263: .getContentNode(contentNodeId);
264: if (node == null) {
265: cat
266: .error("CONTENT_REFERENCE " + getName()
267: + " points to invalid group node: "
268: + contentNodeId);
269: return contentNodes;
270: }
271: TKVector contents = node.getContents();
272: for (int i = 0; i < contents.size(); i++) {
273: SiteContent siteContent = (SiteContent) contents
274: .elementAt(i);
275: String shortName = siteContent.getShortName();
276: int idx = -1;
277: if (shortName != null)
278: idx = searchNames.indexOf(shortName);
279:
280: if (idx != -1) {
281: while (contentNodes.size() <= idx) {
282: contentNodes.addElement(null);
283: }
284: if (siteContent != null
285: && siteContent.isGeneratableVersion()) {
286: cat.debug(" Added " + shortName + " at " + idx);
287: contentNodes.setElementAt(siteContent, idx);
288: } else if (siteContent == null) {
289: cat.error("Content: " + shortName
290: + " is not referenced in the sitetree - "
291: + "content reference is not generated!");
292: } else if (!siteContent.isGeneratableVersion()) {
293: cat.warn("Content: " + shortName
294: + " is not released - "
295: + "content reference is not generated!");
296: }
297: }
298: }
299:
300: // liste aufraeumen
301: for (int i = 0; i < contentNodes.size();) {
302: if (contentNodes.elementAt(i) == null) {
303: contentNodes.removeElementAt(i);
304: } else {
305: i++;
306: }
307: }
308:
309: return contentNodes;
310: }
311:
312: public void fillIntoPresentation(TKHTMLTemplate t, Object data,
313: String scope) {
314: GeneratorContext context = GeneratorContext.setup();
315:
316: context.push();
317: try {
318: TKVector contents = getSelectedContents(data, context);
319: if (contents == null || contents.size() == 0) {
320: super .fillIntoPresentation(t, new TKVector(), scope);
321: return;
322: }
323: if (deliverOnlyNames && contents != null
324: && contents.size() > 0) {
325: if (multipleSelection) {
326: t.set(scope, Integer.toString(contents.size()));
327: t.set(scope + ".SIZE", Integer.toString(contents
328: .size()));
329: t.setListIterator(new GenContentIterator(context,
330: contents, scope, t.getListIterator(),
331: false, true, true));
332: } else {
333: SiteContent content = (SiteContent) contents
334: .firstElement();
335:
336: if (content != null) {
337: content.fillNameIntoTemplate(t, scope + "."
338: + getName());
339: super .fillIntoPresentation(t, content
340: .getShortName(), scope);
341: }
342: }
343: return;
344: }
345: scope += "." + getName();
346:
347: if (contents != null && contents.size() > 0) {
348: if (multipleSelection) {
349: t.set(scope, Integer.toString(contents.size()));
350:
351: /* gck: hab das mal auch so eingefügt, daß man immer
352: auf TK_SCOPE.xxx.SIZE abfragen kann. Ansonsten geht das
353: mit ".SIZE" nämlich nur für ~leere~ content referenz
354: auswahlen, bei content referenz auswahlen ~mit inhalt~
355: beinhaltet nur der SCOPE.xxx die länge der Liste. Wer
356: hat sich das ausgedacht?? */
357: t.set(scope + ".SIZE", Integer.toString(contents
358: .size()));
359:
360: t.setListIterator(new GenContentIterator(context,
361: contents, scope, t.getListIterator(),
362: false, true, false));
363: } else {
364: SiteContent content = (SiteContent) contents
365: .firstElement();
366: if (content != null) {
367: content.fillNameIntoTemplate(t, scope);
368: if (!ReferenceCycleDetector
369: .isCycle(new Integer(content
370: .getInstanceId())))
371: content.fillIntoTemplate(t, scope);
372: }
373: }
374: return;
375: }
376: // Kein Content gefunden -> leerer Listeneintrag !
377: // TKVector names = new TKVector();
378: } finally {
379: context.pop();
380: }
381: }
382:
383: /**
384: * ueberschrieben, um ContentRelationen anlegen zu können
385: */
386: public int insertDataIntoDB(TKContentDBData db, Object data,
387: int contentId, int leftNr) {
388: return super .insertDataIntoDB(db, data, contentId, leftNr);
389: }
390:
391: protected void fillDataIntoNode(Document doc, Element node,
392: Object data) throws DOMException {
393: if (deliverOnlyNames) {
394: super .fillDataIntoNode(doc, node, data);
395: return;
396: }
397: GeneratorContext context = GeneratorContext.setup();
398:
399: TKVector contents = getSelectedContents(data, context);
400: if (contents.size() > 1) {
401: node.setAttribute(MULTIPLE, Boolean.TRUE.toString());
402: } else {
403: node.setAttribute(MULTIPLE, Boolean.FALSE.toString());
404: }
405:
406: // Toplevel Content Element
407: Element me = doc.createElement("content");
408: node.appendChild(me);
409:
410: if (multipleSelection) {
411: for (int i = 0; i < contents.size(); i++) {
412: try {
413: context.push();
414: SiteContent content = (SiteContent) contents
415: .elementAt(i);
416: if (!ReferenceCycleDetector.isCycle(new Integer(
417: content.getInstanceId()))) {
418: content.fillBasicDOM(doc, me);
419: }
420: } finally {
421: context.pop();
422: }
423: }
424: } else {
425: SiteContent content = (SiteContent) contents.firstElement();
426: if (!ReferenceCycleDetector.isCycle(new Integer(content
427: .getInstanceId()))) {
428: context.push();
429: try {
430: content.fillBasicDOM(doc, me);
431: } finally {
432: context.pop();
433: }
434: return;
435: }
436: }
437: }
438:
439: public void initFromDB(String classId, TKFormDBData db,
440: TKVector otherFields) throws TKUnregisteredClassException,
441: ClassNotFoundException, InstantiationException,
442: IllegalAccessException {
443: super .initFromDB(classId, db, otherFields);
444: // contentNodeId = getIntFieldAttribute( db, NODE_KEY, 0 );
445: contentNodeId = Integer.parseInt(getFieldAttribute(db,
446: NODE_KEY, 0));
447: multipleSelection = false;
448: multipleSelection = Boolean.valueOf(
449: getFieldAttribute(db, MULTIPLE_KEY, 0)).booleanValue();
450: deliverOnlyNames = Boolean.valueOf(
451: getFieldAttribute(db, NAME_ONLY_KEY, 0)).booleanValue();
452: }
453:
454: public int realInsertIntoDB(TKFormDBData db, int formId) {
455: if (super .realInsertIntoDB(db, formId) == -1)
456: return -1;
457: insertNewFieldAttribute(db, formId, NODE_KEY, 0, String
458: .valueOf(contentNodeId));
459: insertNewFieldAttribute(db, formId, MULTIPLE_KEY, 0, String
460: .valueOf(multipleSelection));
461: insertNewFieldAttribute(db, formId, NAME_ONLY_KEY, 0, String
462: .valueOf(deliverOnlyNames));
463: return fieldId;
464: }
465:
466: public Object compileData(String prefix, TKMarkupNode data,
467: TKHashtable context) {
468:
469: TKXmlMarkup markup = data == null ? null
470: : (TKXmlMarkup) data.markup;
471: if (markup == null) {
472: return null;
473: }
474:
475: if (!markup.name.equals(getName())) {
476: return null;
477: }
478:
479: TKXmlTree tree = (TKXmlTree) data.tree;
480: if (tree == null) {
481: return null;
482: }
483:
484: String val = tree.getSingleText();
485:
486: if (val == null)
487: return getDefault();
488: else
489: return val.trim();
490: }
491:
492: /**
493: * Checks wether this object and the specified object
494: * may be treated as equal.
495: *
496: * @param object the object to checked for equality.
497: * @return <CODE>true</CODE> if this object and the
498: * specified object may be treated as equal, otherwise
499: * <CODE>false</CODE>.
500: */
501: public boolean equals(Object object) {
502: if (!super .equals(object)) {
503: return false;
504: }
505:
506: TKContentReferenceField field = (TKContentReferenceField) object;
507:
508: return (this .contentNodeId == field.contentNodeId)
509: && (this .multipleSelection == field.multipleSelection)
510: && (this .deliverOnlyNames == field.deliverOnlyNames);
511: }
512:
513: /**
514: * Returns the hash code for this object.
515: *
516: * @return the hash code for this object.
517: */
518: public int hashCode() {
519: // Implementation for JTest only ;-(
520: return super.hashCode();
521: }
522:
523: }
|