KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jahia > services > fields > ContentFieldTools


1 /*
2  * ____.
3  * __/\ ______| |__/\. _______
4  * __ .____| | \ | +----+ \
5  * _______| /--| | | - \ _ | : - \_________
6  * \\______: :---| : : | : | \________>
7  * |__\---\_____________:______: :____|____:_____\
8  * /_____|
9  *
10  * . . . i n j a h i a w e t r u s t . . .
11  *
12  *
13  *
14  * ----- BEGIN LICENSE BLOCK -----
15  * Version: JCSL 1.0
16  *
17  * The contents of this file are subject to the Jahia Community Source License
18  * 1.0 or later (the "License"); you may not use this file except in
19  * compliance with the License. You may obtain a copy of the License at
20  * http://www.jahia.org/license
21  *
22  * Software distributed under the License is distributed on an "AS IS" basis,
23  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
24  * for the rights, obligations and limitations governing use of the contents
25  * of the file. The Original and Upgraded Code is the Jahia CMS and Portal
26  * Server. The developer of the Original and Upgraded Code is JAHIA Ltd. JAHIA
27  * Ltd. owns the copyrights in the portions it created. All Rights Reserved.
28  *
29  * The Shared Modifications are Jahia View Helper.
30  *
31  * The Developer of the Shared Modifications is Jahia Solution S�rl.
32  * Portions created by the Initial Developer are Copyright (C) 2002 by the
33  * Initial Developer. All Rights Reserved.
34  *
35  * Contributor(s):
36  * 09-AUG-2003, Jahia Solutions Sarl, Fulco Houkes
37  *
38  * ----- END LICENSE BLOCK -----
39  */

40
41 package org.jahia.services.fields;
42
43 import java.lang.reflect.Constructor JavaDoc;
44 import java.lang.reflect.InvocationTargetException JavaDoc;
45 import java.util.Hashtable JavaDoc;
46 import java.util.Vector JavaDoc;
47
48 import org.apache.log4j.Logger;
49 import org.jahia.exceptions.JahiaException;
50 import org.jahia.exceptions.JahiaInitializationException;
51 import org.jahia.registries.ServicesRegistry;
52 import org.jahia.services.acl.JahiaBaseACL;
53 import org.jahia.services.cache.Cache;
54 import org.jahia.services.cache.CacheFactory;
55 import org.jahia.services.usermanager.JahiaUser;
56 import org.jahia.services.version.ContentObjectEntryState;
57 import org.jahia.services.version.StateModificationContext;
58
59 class ContentFieldTools {
60
61     /** logging */
62     final private Logger logger = Logger.getLogger (ContentFieldTools.class);
63
64     /** this class unique instance */
65     private static ContentFieldTools instance;
66
67     // the Content Field cache name.
68
public static final String JavaDoc CONTENT_FIELD_CACHE = "ContentFieldCache";
69     /** Fields cache */
70     private static Cache cacheFields;
71
72     private Hashtable JavaDoc fieldClassNames;
73     private Hashtable JavaDoc fieldClassConstructor = new Hashtable JavaDoc ();
74
75
76     /**
77      * Default constructor, creates a new <code>ContentFieldTools</code> instance.
78      */

79     private ContentFieldTools () {
80         logger.info ("***** Starting up the ContentFieldTools singleton *****");
81
82         try {
83             cacheFields = CacheFactory.createCache (CONTENT_FIELD_CACHE);
84
85         } catch (JahiaInitializationException e) {
86             logger.warn (e);
87         }
88
89         // get the hashtable which give the class name
90
// which correspond to the field type.
91
fieldClassNames = ContentFieldTypes.getInstance ().getFieldClassNames ();
92     }
93
94     /**
95      * Return the unique instance of this class
96      *
97      * @return the unique instance of this class
98      */

99     public static synchronized ContentFieldTools getInstance () {
100         if (instance == null) {
101             instance = new ContentFieldTools ();
102         }
103
104         return instance;
105     }
106
107     /**
108      * Creates a ContentField value in RAM, with no content
109      * This method should be called to create a field, and the field content should be set right
110      * after that! This method allocates a new AclID and fieldID so don't play with it if you
111      * don't have a firm intention to create a field ;)
112      *
113      * @return the created content field. Do a set on it right after, if no set is done, the
114      * field will never be written to the DB ! (but its acl won't be deleted)
115      */

116     protected ContentField createField (int siteID, int pageID, int containerID, int fieldDefID, int typeField,
117                                         int connectType, int parentAclID, int aclID)
118             throws JahiaException {
119         // create new field id
120
int theFieldID = ServicesRegistry.getInstance ().getJahiaIncrementorsDBService ()
121                 .autoIncrement ("jahia_fields_data");
122
123         // create new ACL id
124
if (aclID == 0) {
125             JahiaBaseACL acl = new JahiaBaseACL ();
126             if (acl != null) {
127                 // create a new object by specifying the parent ACL ID (a container)
128
if (!acl.create (parentAclID)) {
129                     String JavaDoc message = "Could not create an ACL object for a new field in container.";
130                     logger.debug (message + " -> Stop container creation!");
131                     throw new JahiaException ("AddContainer_Engine", message,
132                             JahiaException.ACL_ERROR, JahiaException.CRITICAL_SEVERITY);
133                 } else {
134                     logger.debug ("ACL [" + acl.getID () + "] has just been created!");
135                 }
136             } else {
137                 throw new JahiaException ("ContentFieldBaseService.saveField", "Could not instanciate the JahiaBaseACL class",
138                         JahiaException.ACL_ERROR, JahiaException.CRITICAL_SEVERITY);
139             }
140             // End Create ACL
141
aclID = acl.getID (); // we store the new acl in aclID
142
}
143
144         return createContentFieldInstance (theFieldID, siteID, pageID, containerID,
145                 fieldDefID, typeField, connectType,
146                 aclID, new Vector JavaDoc (), new Hashtable JavaDoc ());
147     }
148
149     /**
150      * Preloads all the active or staged fields for a given page into the
151      * fields cache.
152      *
153      * @param pageID the page ID for which to preload all the content fields
154      *
155      * @throws JahiaException thrown if there was an error while loading the
156      * fields from the database.
157      */

158     protected void preloadActiveOrStagedFieldsByPageID (int pageID)
159             throws JahiaException {
160         ContentFieldDB.getInstance ().preloadActiveOrStagedFieldsByPageID (pageID, cacheFields);
161     }
162
163     /**
164      * Preloads all the active or staged fields for a given container into the
165      * field cache.
166      *
167      * @param containerID the container ID for which to preload all the content fields
168      *
169      * @throws JahiaException thrown if there was an error while loading the fields from the database.
170      */

171     protected void preloadActiveOrStagedFieldsByContainerID (int containerID)
172             throws JahiaException {
173         ContentFieldDB.getInstance ().preloadActiveOrStagedFieldsByContainerID(containerID,
174                 cacheFields);
175     }
176
177     /**
178      * Get a ContentField from its ID
179      *
180      * @param fieldID
181      *
182      * @throws JahiaException if the field doesn't exist, or there's a DB error
183      */

184     public ContentField getField (int fieldID)
185             throws JahiaException {
186         return getField (fieldID, false);
187     }
188
189     /**
190      * This method needs to be called whenever we do internal modifications
191      * to a ContentField, in order to make sure the cache is informed the
192      * field has been modified and can sync the new values in the cluster.
193      * @param contentField ContentField
194      */

195     public void updateCache(ContentField contentField) {
196         cacheFields.put(new Integer JavaDoc(contentField.getID()), contentField);
197     }
198
199     /**
200      * Get a ContentField from its ID
201      *
202      * @param fieldID
203      * @param forceLoadFromDB if true, force loading from db
204      *
205      * @throws JahiaException If the field doesn't exist, or there's a DB error
206      */

207     public ContentField getField(int fieldID, boolean forceLoadFromDB) throws JahiaException {
208         ContentField cachedField = null;
209
210         if (!forceLoadFromDB) {
211             cachedField = (ContentField) cacheFields.get(new Integer JavaDoc(fieldID));
212             if (cachedField != null)
213                 return cachedField;
214         }
215         cachedField = ContentFieldDB.getInstance().loadContentFieldDB(fieldID);
216         if (cachedField != null) {
217             cacheFields.put(new Integer JavaDoc(fieldID), cachedField);
218         }
219         return cachedField;
220     }
221
222     public ContentField getContentFieldFromCacheOnly (int fieldId) {
223         return (ContentField)cacheFields.get(new Integer JavaDoc (fieldId));
224     }
225     
226     /**
227      * Delete a ContentField from its ID
228      * (This is a user request. In fact, it just puts a "delete flag" on every language of
229      * The field, and the field will really be delete when the page is staging-validated
230      * and versioning is disabled)
231      *
232      * @param theField the ID of the field to delete (should be synchronized!)
233      * @param user the user performing the marking
234      * @param activeAndStagingEntryStates the corresponding vector coming from the contentfield
235      * @param stateModifContext used to detect loops in deletion marking.
236      */

237     public void markFieldForDeletion (ContentField theField,
238                                       JahiaUser user,
239                                       Vector JavaDoc activeAndStagingEntryStates,
240                                       StateModificationContext stateModifContext)
241             throws JahiaException {
242         for (int i = 0; i < activeAndStagingEntryStates.size (); i++) {
243             ContentObjectEntryState entryState = (ContentObjectEntryState) activeAndStagingEntryStates.elementAt (
244                     i);
245             // we now have a new save request where we've specified the lanstateModifContextguage!
246
theField.markLanguageForDeletion (user, entryState.getLanguageCode (),
247                     stateModifContext);
248         }
249     }
250
251     /**
252      * This method should ONLY be called when a field must be COMPLETELY deleted.
253      * It's the case when a validate is done and no more active&staging version of the
254      * field exist, and versioning is disabled (so there are no versioning versions either).
255      * In this case, this method should be called by the validate method.
256      *
257      * @param theField the field to delete
258      */

259     public void purgeFieldData (ContentField theField)
260             throws JahiaException {
261         // removes ACL & ACL entries corresponding to this field
262
theField.getACL ().delete ();
263     }
264
265     /**
266      * Set a field (dump it to database etc)
267      * 1. if indexed for the search engine, remove old field value
268      * 2. if versioning is enable & modified field is active, calls backupFieldVersion for this field
269      * 3. do database work and update versions of the loadedFieldData hashtable & Vectors in the field
270      * 3.b. if value is <no_value> then delete the version of this field
271      * 4. add new field value to search engine
272      * @param theField the field to dump to database
273      * @param newVersionID the new version ID of this field (from VersionService.getCurrentVersionID())
274
275      */

276 /* public void setField (ContentField theField, int newVersionID)
277         throws JahiaException
278     {
279         synchronized (theField)
280         {
281             for (Enumeration e = theField.loadedDBValues.keys() ; e.hasMoreElements() ;)
282             {
283                 ContentFieldVersionInfo thisVersionInfo = (ContentFieldVersionInfo)e.nextElement();
284                 // we only update active & staged fields, not inactive ones
285                 if (thisVersionInfo.isStaging() || thisVersionInfo.isActive())
286                 {
287                     ContentField.DBValue dbValue = (ContentField.DBValue)theField.loadedDBValues.get(thisVersionInfo);
288                     // is this field modified or new ?
289                     if ((dbValue.getOldValue() != null) ||
290                        (thisVersionInfo.isNew()))
291                     {
292                         // yessss, let's start the update process
293
294                         // if this field ain't new and is active, remove field content from search engine
295                         if ((!thisVersionInfo.isNew())
296                             && (thisVersionInfo.isActive()))
297                         {
298                             //TODO remove from search engine
299                             String s = theField.getValueForSearch(dbValue.getOldValue(), thisVersionInfo.getLanguageCode());
300                             //if ((s!=null)&&(!s.equals("")))
301                             //ServicesRegistry.getInstance().getJahiaSearchService().removeFieldFromSearchEngine( );
302                         }
303
304                         // if versioning is enable, and staging is not enabled backup old version of this field
305                         if ( theField.verService.isVersioningEnabled(theField.getSiteID()) &&
306                              thisVersionInfo.isActive() )
307                         {
308                             backupDBValue(theField);
309                         }
310
311                         // if its value is "<no_value>" it means we want to delete it
312                         if (dbValue.getValue().equals(ContentField.NO_VALUE))
313                         {
314                             deleteDBValue(theField, thisVersionInfo);
315
316                             // remove the version from the activeAndStagingVersionInfo
317                             theField.activeAndStagingVersionInfo.remove(thisVersionInfo);
318                             // we must remove it from the hashtable too
319                             theField.loadedDBValues.remove(thisVersionInfo);
320
321
322                         } else
323                         // okay, we're here to create or update, but not delete!
324                         {
325                             // remove the version from the activeAndStagingVersionInfo
326                             theField.activeAndStagingVersionInfo.remove(thisVersionInfo);
327                             // we must remove it from the hashtable to change the version ID
328                             theField.loadedDBValues.remove(thisVersionInfo);
329                             // update versionID with new version
330                             thisVersionInfo.setVersionID(newVersionID);
331                             // we put it back in the hashtable, with oldvalue = null so we now it's synched with DB
332                             theField.loadedDBValues.put(thisVersionInfo, theField.newDBValue(dbValue.getValue(),null));
333                             // remove the version from the activeAndStagingVersionInfo
334                             theField.activeAndStagingVersionInfo.add(thisVersionInfo);
335
336                             // if the version is new we create a new field version
337                             if (thisVersionInfo.isNew())
338                             {
339                                 createDBValue(theField, thisVersionInfo);
340                             }
341
342                             // we update it with the new value
343                             updateDBValue(theField, thisVersionInfo);
344                             // add new field content from search engine
345                             if (thisVersionInfo.isActive())
346                             {
347                                 //TODO add to search engine
348                                 String s = theField.getValueForSearch(dbValue.getValue(), thisVersionInfo.getLanguageCode());
349                                 //if ((s!=null)&&(!s.equals("")))
350                                 //ServicesRegistry.getInstance().getJahiaSearchService().addFieldToSearchEngine( );
351                             }
352                         }
353                     }
354                 }
355             }
356         }
357     }*/

358
359     /**
360      * Delete a ContentField
361      * In fact, it puts <no_value> for every language of this field, and then
362      * call setField
363      */

364 /* public void deleteField (int fieldID)
365         throws JahiaException
366     {
367         ContentField theField = getField(fieldID);
368         boolean staged = theField.verService.isStagingEnabled(theField.getSiteID());
369         synchronized (theField)
370         {
371             for (int i=0;i<theField.activeAndStagingVersionInfo.size();i++)
372             {
373                 ContentFieldVersionInfo verInfo=(ContentFieldVersionInfo)theField.activeAndStagingVersionInfo.elementAt(i);
374                 theField.setDBValue(verInfo.getLanguageCode(), ContentField.NO_VALUE);
375             }
376         }
377         setField (theField, theField.verService.getCurrentVersionID());
378     }*/

379
380     /**
381      * Clone a ContentField
382      */

383     protected ContentField cloneField (int fieldID)
384             throws JahiaException {
385         return null; /** @todo implement cloneField */
386     }
387
388     /**
389      * create a new ContentField instance. This is the only
390      * method that should be called to create a new JahiaField
391      * object, and usually you shouldn't need to call this
392      * method but use getField or createField instead!
393      */

394     protected ContentField createContentFieldInstance (int ID,
395                                                        int jahiaID,
396                                                        int pageID,
397                                                        int ctnid,
398                                                        int fieldDefID,
399                                                        int fieldType,
400                                                        int connectType,
401                                                        int aclID,
402                                                        Vector JavaDoc activeAndStagingEntryStates,
403                                                        Hashtable JavaDoc activeAndStagedDBValues)
404             throws JahiaException {
405         ContentField theField;
406
407         try {
408
409             // get the constructor by its name
410
// the name come from the hashtable
411
Integer JavaDoc fieldTypeInt = new Integer JavaDoc (fieldType);
412             Constructor JavaDoc thisConstructor = null;
413             if (fieldClassConstructor.containsKey (fieldTypeInt)) {
414                 thisConstructor = (Constructor JavaDoc) fieldClassConstructor.get (fieldTypeInt);
415             } else {
416                 // define the types of the parameter of the constructor
417
Class JavaDoc theParams[] = {Integer JavaDoc.class,
418                                      Integer JavaDoc.class,
419                                      Integer JavaDoc.class,
420                                      Integer JavaDoc.class,
421                                      Integer JavaDoc.class,
422                                      Integer JavaDoc.class,
423                                      Integer JavaDoc.class,
424                                      Integer JavaDoc.class,
425                                      Vector JavaDoc.class,
426                                      Hashtable JavaDoc.class};
427
428                 thisConstructor = Class.forName ((String JavaDoc) fieldClassNames.
429                         get (new Integer JavaDoc (fieldType))).
430                         getDeclaredConstructor (theParams);
431                 fieldClassConstructor.put (fieldTypeInt, thisConstructor);
432             }
433
434             // the parameter values of the constructor
435
Object JavaDoc args[] = {new Integer JavaDoc (ID), new Integer JavaDoc (jahiaID),
436                              new Integer JavaDoc (pageID), new Integer JavaDoc (ctnid),
437                              new Integer JavaDoc (fieldDefID),
438                              new Integer JavaDoc (fieldType),
439                              new Integer JavaDoc (connectType),
440                              new Integer JavaDoc (aclID),
441                              activeAndStagingEntryStates,
442                              activeAndStagedDBValues};
443
444             // call the constructor
445
theField = (ContentField) thisConstructor.newInstance (args);
446
447         } catch (ClassNotFoundException JavaDoc cnfe) {
448             cnfe.printStackTrace ();
449             throw new JahiaException ("ContentFieldTools.createContentFieldInstance",
450                     "Class not found!",
451                     JahiaException.PAGE_ERROR, JahiaException.CRITICAL_SEVERITY,
452                     cnfe.getException ());
453
454         } catch (NoSuchMethodException JavaDoc nsme) {
455             throw new JahiaException ("JahiaContentBaseService:createContentFieldInstance",
456                     "Method not found!",
457                     JahiaException.PAGE_ERROR, JahiaException.CRITICAL_SEVERITY, nsme);
458
459         } catch (IllegalAccessException JavaDoc iae) {
460             throw new JahiaException ("JahiaContentBaseService:createContentFieldInstance",
461                     "Illegal access",
462                     JahiaException.PAGE_ERROR, JahiaException.CRITICAL_SEVERITY, iae);
463
464         } catch (InvocationTargetException JavaDoc ite) {
465             throw new JahiaException ("JahiaContentBaseService:createContentFieldInstance",
466                     "InvocationTarget exception",
467                     JahiaException.PAGE_ERROR, JahiaException.CRITICAL_SEVERITY,
468                     ite.getTargetException ());
469
470         } catch (InstantiationException JavaDoc ie) {
471             throw new JahiaException ("JahiaContentBaseService:createContentFieldInstance",
472                     "Instantiation exception",
473                     JahiaException.PAGE_ERROR, JahiaException.CRITICAL_SEVERITY, ie);
474         }
475         // return the new ContentField
476
return theField;
477     }
478
479     /**
480      * Removes a field from the cache if it was present in the cache. If not,
481      * this does nothing.
482      *
483      * @param fieldID the identifier for the field to try to remove from the
484      * cache.
485      */

486     public void removeFromCache (int fieldID) {
487         cacheFields.remove (new Integer JavaDoc (fieldID));
488     }
489
490     /**
491      * reset the page preloaded fields status , so that the preloading operation
492      * can be performed again the next page access
493      *
494      * @param pageId int
495      */

496     public synchronized void allowFieldsPreloadingForPage(int pageId){
497         ContentFieldDB.getInstance().allowFieldsPreloadingForPage(pageId);
498     }
499
500 }
501
Popular Tags