KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jahia > data > fields > JahiaFieldSet


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 // EV 31.10.2000
14
// JT 14.08.2001
15

16 package org.jahia.data.fields;
17
18 import java.util.ArrayList JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.HashSet JavaDoc;
22 import java.util.Hashtable JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.Locale JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.Properties JavaDoc;
27 import java.util.Set JavaDoc;
28
29 import org.jahia.data.JahiaData;
30 import org.jahia.exceptions.JahiaException;
31 import org.jahia.registries.JahiaFieldDefinitionsRegistry;
32 import org.jahia.registries.ServicesRegistry;
33 import org.jahia.services.fields.ContentField;
34 import org.jahia.services.pages.JahiaPage;
35 import org.jahia.services.version.EntryLoadRequest;
36
37 public class JahiaFieldSet implements Map JavaDoc {
38
39     private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(JahiaFieldSet.class);
40
41     private JahiaData jData;
42
43     /**
44      * @associates JahiaField
45      */

46     private Map JavaDoc fields;
47
48     /**
49      * @associates String
50      */

51     private Set JavaDoc declaredFields;
52
53     /**
54      * key = field name / value = Properties
55      */

56     private Hashtable JavaDoc declaredFieldDefProps;
57
58     /**
59      * This is used to store during a request all the fields that have
60      * been accessed in absolute manner. This will be used to figure out if the
61      * absolute references have changed since the last time this template was
62      * processed.
63      */

64     private Set JavaDoc absoluteFieldAccesses = new HashSet JavaDoc();
65
66
67     /***
68      * constructor
69      * EV 29.12.2000
70      *
71      */

72     public JahiaFieldSet( JahiaData jData )
73     throws JahiaException
74     {
75         this.jData = jData;
76         this.fields = new HashMap JavaDoc();
77         this.declaredFields = new HashSet JavaDoc();
78         this.declaredFieldDefProps = new Hashtable JavaDoc();
79
80     } // end constructor
81

82
83     /***
84      * EV 29.12.2000
85      *
86      */

87     public void addField( JahiaField theField )
88     throws JahiaException
89     {
90         fields.put( theField.getDefinition().getName(), theField );
91     } // end addFieldList
92

93
94     /***
95      * EV 29.12.2000
96      *
97      */

98     public void removeField( JahiaField theField )
99     throws JahiaException
100     {
101         fields.remove( theField.getDefinition().getName() );
102     } // end removeFieldList
103

104
105     /***
106      * EV 29.12.2000
107      *
108      */

109     public void declareField( String JavaDoc fieldName, String JavaDoc fieldTitle, int fieldType, String JavaDoc defaultValue )
110     throws JahiaException
111     {
112
113         synchronized ( JahiaFieldSet.class ) {
114
115             logger.debug( "fieldName="+fieldName+", defValue=" + defaultValue );
116
117             // we check if a field with the same name was not already declared, of if the field has no
118
// empty name or title
119
if (checkDeclared(fieldName) ||
120                 jData.containers().checkDeclared(fieldName) ||
121                 fieldName.length() == 0 || fieldTitle.length() == 0) {
122                 // the field is already declared, or has a null name/title : let the user have it... ;)
123
String JavaDoc errorMsg = "Field already declared or has a null name - title : " + fieldName;
124                 logger.debug( ".declareField," + errorMsg + " -> BAILING OUT" );
125                 throw new JahiaException( errorMsg, errorMsg, JahiaException.TEMPLATE_ERROR,
126                                         JahiaException.CRITICAL_SEVERITY );
127             } else {
128                 // first, let's check to see if the declared field has already a field definition in the
129
// FieldsDefinitionsRegistry (which means also in the jahia_fields_def table)
130
JahiaFieldDefinitionsRegistry fldDefRegistry = JahiaFieldDefinitionsRegistry.getInstance();
131                 JahiaFieldDefinition aDef = fldDefRegistry.getDefinition( jData.params().getSiteID(),fieldName );
132                 int pageDefID = jData.params().getPage().getPageTemplateID();
133                 if (aDef != null) {
134
135                     Properties JavaDoc props = aDef.getProperties();
136                     Properties JavaDoc declaredProps = (Properties JavaDoc)this.declaredFieldDefProps.get(fieldName);
137
138                     boolean propsHasChanged = (
139                             (props == null && (declaredProps != null && declaredProps.size()>0)) ||
140                            ( (props != null && props.size()>0) && declaredProps == null )
141                           || ( props != null && declaredProps != null && !props.equals(declaredProps) ) );
142
143                     // okay, it seems the definition already exists.
144
// now has it the same data than in the database (title, type, defaultval) ?
145
if ( aDef.getType(pageDefID) == -1 ){
146                         // sub def for this page def doesn't exist
147
// have to create it
148
logger.debug(".declareField, Create new field sub def for pageDef=" + pageDefID + " and fieldName=" + fieldName + "");
149                         aDef.setType( fieldType, pageDefID );
150                         aDef.setTitle( fieldTitle, pageDefID );
151                         aDef.setDefaultValue( defaultValue, pageDefID );
152                         aDef.setProperties((Properties JavaDoc)this.declaredFieldDefProps.get(fieldName));
153                         fldDefRegistry.setDefinition( aDef );
154
155                     } else if (!((aDef.getTitle(pageDefID).equals(fieldTitle)) &&
156                         (aDef.getType(pageDefID) == fieldType) &&
157                         (aDef.getDefaultValue(pageDefID).equals(defaultValue)) &&
158                         !propsHasChanged)) {
159
160                         logger.debug(".declareField, Field Data for field " + fieldName +
161                                              " is not synchronized between template and database !" );
162
163                         if ( !aDef.getTitle(pageDefID).equals(fieldTitle) ){
164                             logger.debug(".declareField, Title: " +
165                                                  aDef.getTitle(pageDefID) +
166                                                  " is not equal to " + fieldTitle + "" );
167                         }
168
169                         if ( aDef.getType(pageDefID) != fieldType ){
170                             logger.debug(".declareField, Type: " +
171                                                  aDef.getType(pageDefID) +
172                                                  " is not equal to " + fieldType + "");
173                         }
174
175                         if ( !aDef.getDefaultValue(pageDefID).equals(defaultValue) ){
176                             if (defaultValue.length() > 250) { /** @todo FIXME this
177                                 hardcoded value comes from database field declaration */

178                                 logger.debug(".declareField, Default value is too big to fit in database.");
179                             } else {
180                                 logger.debug(".declareField, Default Value: " +
181                                                      aDef.getDefaultValue(pageDefID) +
182                                                      "\n is not equal to \n" + defaultValue + "");
183                             }
184                         }
185                         // well, data is not the same in the registry and in the declare() method !
186
// this means the user has changed the field declaration in the template...
187
// before doing anything else, we have to be sure that the user didn't change the
188
// field data type, because this could crash the whole application !
189
if ((aDef.getType(pageDefID) != fieldType) && (aDef.getType(pageDefID) != -1)) {
190                             // okay, this user think he's smart : he tried to change the data type of
191
// fields already existing...
192
// let's send him a Jahia error to learn him a little lesson
193
String JavaDoc errorMsg = "Cannot change field type because field data already exists : " + fieldName;
194                             logger.debug( ".declareField, " + errorMsg + " -> BAILING OUT" );
195                             throw new JahiaException( errorMsg, errorMsg, JahiaException.TEMPLATE_ERROR,
196                                         JahiaException.CRITICAL_SEVERITY );
197
198                         } else {
199                             // okay, no alert ahead, the type hasn't been modified
200
// let's synchronize the data between :
201
// - the template declaration (file)
202
// - the database declaration (database)
203
// - the registry declaration (memory)
204
// the synchronizeData method handles all this for us... pfew :)
205
aDef.setType( fieldType, pageDefID );
206                             aDef.setTitle( fieldTitle, pageDefID );
207                             aDef.setDefaultValue( defaultValue, pageDefID );
208                             aDef.setProperties((Properties JavaDoc)this.declaredFieldDefProps.get(fieldName));
209                             fldDefRegistry.setDefinition( aDef );
210                         }
211                     }
212                 } else {
213                     // hell, the definition doesn't exist in the memory !
214
// this can mean two things :
215
// - either this is the first time Jahia encounters this template
216
// - or the database data was screwed
217
// in any case, we got to :
218
// - add it into the registry (memory)
219
// - add it into the database (database)
220
// - change the values in jData (memory)
221
Hashtable JavaDoc subDefs = new Hashtable JavaDoc();
222                     subDefs.put( new Integer JavaDoc(pageDefID), new JahiaFieldSubDefinition( 0, 0, pageDefID, fieldTitle, fieldType, defaultValue ) );
223                     aDef = new JahiaFieldDefinition( 0, jData.params().getPage().getJahiaID(),
224                                                     fieldName, subDefs );
225
226                     aDef.setProperties((Properties JavaDoc)this.declaredFieldDefProps.get(fieldName));
227
228                     fldDefRegistry.setDefinition( aDef );
229
230                 }
231
232                 // we check to see if the declared field was already present in the database
233
JahiaField theField = (JahiaField) fields.get( fieldName );
234                 // if the field is null :
235
// - create the field
236
// - store it in the database
237
// - adds it in the bean fields vector
238
if (theField == null) {
239
240                     // create the new field only if the staged one doesn't exists
241
EntryLoadRequest currentEntryLoadRequest = jData.params().getEntryLoadRequest();
242
243                     int fieldID = ServicesRegistry.getInstance().getJahiaFieldService()
244                                                 .getFieldID( fieldName, jData.params().getPageID() );
245
246                     Locale JavaDoc currentLocale = jData.params().getEntryLoadRequest().getFirstLocale(true);
247
248                     boolean fieldCurrentlyExists = false;
249                     if ((fieldID != -1)) {
250                         // now we must check if it exists in active or staging
251
ContentField curField = ContentField.getField(fieldID);
252                         if ((curField.hasActiveEntries()) ||
253                             (curField.hasStagingEntries())) {
254                             fieldCurrentlyExists = true;
255                         } else {
256                             // we must remove it from the cache in order to
257
// stay compatible with the legacy here below...
258
/** @todo FIXME remove the legacy below in order to
259                              * be able to remove this too...
260                              */

261                             logger.debug("Field " + fieldID +
262                                          " found in versioned or deleted state but not active or staged, creating new staged...");
263                             ContentField.removeFromCache(fieldID);
264                         }
265                     }
266
267                     if ( !fieldCurrentlyExists )
268                     {
269                         // the field doesn't exist at all
270
// so we create it
271
String JavaDoc fieldDefValue = "";
272                         if ( defaultValue.indexOf("jahia_multivalue") == -1 ){
273                             fieldDefValue = defaultValue;
274                         }
275
276                         int useFieldID = 0;
277                         if (fieldID != -1) {
278                             useFieldID = fieldID;
279                         }
280
281                         JahiaField newField = ServicesRegistry.getInstance().
282                                               getJahiaFieldService().createJahiaField(
283                                               useFieldID, jData.params().getPage().getJahiaID(),
284                                               jData.params().getPage().getID(),0,
285                                               aDef.getID(), fieldType, 0,
286                                               fieldDefValue, 0, 0, 0,
287                                               EntryLoadRequest.STAGING_WORKFLOW_STATE,
288                                               currentLocale.toString());
289
290                         // this is a horrible hack to tell the save service to
291
// reuse a field ID when saving to the database.
292
if (fieldID != -1) {
293                             newField.setObject("createFieldWithCurrentID");
294                         }
295
296                         ServicesRegistry.getInstance().getJahiaFieldService()
297                                 .saveField( newField, jData.params().getPage().getAclID(), jData.params() );
298
299                         // Force the field to be loaded from database as if it was loaded for the first time.
300
// Doing so, we ensure that all load field treatment are applied.
301
newField = ServicesRegistry.getInstance().getJahiaFieldService().loadField( newField.getID(), LoadFlags.ALL, jData.params(), currentEntryLoadRequest );
302
303                         // we add the field only if its workflow status matches the request entry load request
304
if ( newField != null && (currentEntryLoadRequest.getWorkflowState () == newField.getWorkflowState ()) ) {
305                             addField( newField );
306                         }
307                         logger.debug(".declareField, created new field with name=" + aDef.getName());
308                     } else {
309                         // does it exists in the requested language, if not, return the first available language.
310
JahiaField newField = ServicesRegistry.getInstance()
311                                 .getJahiaFieldService().loadField( fieldID, LoadFlags.ALL, jData.params(), currentEntryLoadRequest );
312                         if ( newField == null ){
313                             // doesn't exists in requested language
314
ArrayList JavaDoc siteLocales = jData.params().getSite().getLanguageSettingsAsLocales(true);
315                             JahiaContentFieldFacade fieldFacade =
316                                 new JahiaContentFieldFacade(fieldID,LoadFlags.ALL,jData.params(),siteLocales,true);
317                             newField = fieldFacade.getField(jData.params().getEntryLoadRequest(),true);
318                         }
319
320                         // we add the field only if its workflow status matches the request entry load request
321
if ( newField != null ) {
322                             addField( newField );
323                         }
324                     }
325                 }
326
327                 // we declare that the field has been loaded, in order to avoid double definitions
328
declaredFields.add( fieldName );
329             }
330         }
331
332     } // end declareField
333

334     /**
335      * Declare properties for a given field definition ( field name )
336      *
337      * @param fieldName
338      * @param propName
339      * @param propValue
340      */

341     public void declareFieldDefProp(String JavaDoc fieldName,
342                                     String JavaDoc propName,
343                                     String JavaDoc propValue){
344         if ( fieldName != null && propName != null && propValue != null ){
345             Properties JavaDoc props = (Properties JavaDoc)this.declaredFieldDefProps.get(fieldName);
346             if ( props == null ){
347                 props = new Properties JavaDoc();
348             }
349             props.setProperty(propName, propValue);
350             this.declaredFieldDefProps.put(fieldName,props);
351         }
352     }
353
354
355     /***
356         * checkDeclared
357         * EV 29.12.2000
358         *
359         */

360     public boolean checkDeclared( String JavaDoc fieldName )
361     {
362         return declaredFields.contains(fieldName);
363     } // end checkDeclared
364

365
366
367     /***
368         * getField
369         * EV 29.12.2000
370         *
371         * !!! Warning : this method can return a null value !!!
372         */

373     public JahiaField getField( String JavaDoc fieldName )
374     throws JahiaException
375     {
376         if (checkDeclared( fieldName ))
377         {
378             JahiaField theField = (JahiaField) fields.get( fieldName );
379                 return theField;
380         }
381         return null;
382     } // end getField
383

384
385
386     /***
387         * getField
388         * EV 29.12.2000
389         *
390         * !!! Warning : this method can return a null value !!!
391         */

392     public JahiaField getField( int fieldID )
393     throws JahiaException
394     {
395         Iterator JavaDoc fieldIter = fields.values().iterator();
396         while (fieldIter.hasNext()) {
397             JahiaField aField = (JahiaField) fieldIter.next();
398             if (aField.getID() == fieldID) {
399                 return aField;
400             }
401         }
402         return null;
403     } // end getField
404

405
406
407     //-------------------------------------------------------------------------
408
/***
409      * gets a field in another page (absolute page reference by its id)
410      *
411      * @param fieldName the field name
412      * @param pageID the page ID
413      * @return a JahiaField object, or null if nothing found
414      * @see org.jahia.data.fields.JahiaField
415      *
416      * !!! Warning : this method can return a null value !!!
417      */

418     public JahiaField getAbsoluteField( String JavaDoc fieldName, int pageID )
419     throws JahiaException
420     {
421         logger.debug("for field " + fieldName );
422         int fieldID = ServicesRegistry.getInstance().getJahiaFieldService(
423                                 ).getFieldID( fieldName, pageID );
424         JahiaField theField = null;
425         if (fieldID != -1)
426         {
427             // let's update cross reference list
428
absoluteFieldAccesses.add(new Integer JavaDoc(fieldID));
429
430             //System.out.println( " found field ID : " + fieldID );
431
theField = getField(fieldID);
432             if ( theField == null )
433             {
434                 logger.debug("Field not in cache " + fieldID );
435
436                 theField = ServicesRegistry.getInstance()
437                                             .getJahiaFieldService()
438                                             .loadField( fieldID, LoadFlags.ALL, jData.params() );
439                 if ( theField == null ){
440                     // doesn't exists in requested language
441
ArrayList JavaDoc siteLocales = jData.params().getSite().getLanguageSettingsAsLocales(true);
442                     JahiaContentFieldFacade fieldFacade =
443                         new JahiaContentFieldFacade(fieldID,LoadFlags.ALL,jData.params(),siteLocales,true);
444                     theField = fieldFacade.getField(jData.params().getEntryLoadRequest(),true);
445                 }
446             }
447         }
448         if ( theField != null ){
449             logger.debug("Returned field " + fieldID + " value " + theField.getValue());
450
451             return theField;
452         } else {
453             // not found : gets definition id, then creates fake field and saves it into memory
454
JahiaFieldDefinition fieldDef = JahiaFieldDefinitionsRegistry.getInstance().
455                     getDefinition( jData.params().getSiteID(), fieldName );
456             JahiaPage sourcePage = ServicesRegistry.getInstance().getJahiaPageService().
457                     lookupPage( pageID, jData.params() );
458             if (sourcePage != null) {
459                 //System.out.println( " sourcePage is not null !" );
460
int pageDefID = sourcePage.getPageTemplateID();
461                 if (fieldDef != null) {
462                     //System.out.println( " fieldDef is not null !" );
463
int fieldType = fieldDef.getType(pageDefID);
464                     if (fieldType != -1) {
465                         // let's update cross reference table
466
//System.out.println( " fieldType is " + fieldType );
467
//JahiaField fakeField = new JahiaField(0, fieldDef.getJahiaID(),
468
// pageID, 0, fieldDef.getID(), fieldDef.getType(0), 0,
469
// fieldDef.getDefaultValue(fieldDef.getID()), 0, 0 );
470
JahiaField fakeField = ServicesRegistry.getInstance().
471                                    getJahiaFieldService().createJahiaField(
472                                    0, fieldDef.getJahiaID(), pageID, 0,
473                                    fieldDef.getID(), fieldType, 0,
474                                    fieldDef.getDefaultValue(fieldDef.getID()),
475                                    0, 0);
476                         addField( fakeField );
477
478                         absoluteFieldAccesses.add(new Integer JavaDoc(fakeField.getID()));
479                         return fakeField;
480                     }
481                 }
482             }
483             return null;
484         }
485     } // end getAbsoluteField
486

487     /**
488      * Returns a map that contains the current mapping of field -> page that
489      * represent the fields that have been accessed by pages using the
490      * absolute addressing method.
491      *
492      * @return a Set containing Integer objects. These represents field IDs
493      * that have been accessed in an absolute way by the current page.
494      */

495     public Set JavaDoc getAbsoluteFieldAccesses() {
496         return absoluteFieldAccesses;
497     }
498
499     /*
500         Map interface implementation methods
501      */

502
503     public boolean equals(Object JavaDoc o) {
504         return fields.equals(o);
505     }
506
507     public int hashCode() {
508         return fields.hashCode();
509     }
510
511     public Set JavaDoc entrySet () {
512         return fields.entrySet();
513     }
514
515     public Collection JavaDoc values () {
516         return fields.values();
517     }
518
519     public Set JavaDoc keySet () {
520         return fields.keySet();
521     }
522
523     public void clear ()
524         throws UnsupportedOperationException JavaDoc {
525         throw new UnsupportedOperationException JavaDoc(
526             "Jahia field collection is read-only!");
527     }
528
529     public void putAll (Map JavaDoc t)
530         throws UnsupportedOperationException JavaDoc {
531         throw new UnsupportedOperationException JavaDoc(
532             "Jahia field collection is read-only!");
533     }
534
535     public Object JavaDoc remove (Object JavaDoc key)
536         throws UnsupportedOperationException JavaDoc {
537         throw new UnsupportedOperationException JavaDoc(
538             "Jahia field collection is read-only!");
539     }
540
541     public Object JavaDoc put (Object JavaDoc key,
542                        Object JavaDoc value)
543         throws UnsupportedOperationException JavaDoc {
544         throw new UnsupportedOperationException JavaDoc(
545             "Jahia field collection is read-only!");
546     }
547
548     public Object JavaDoc get (Object JavaDoc key) {
549         return fields.get(key);
550     }
551
552     public boolean containsValue (Object JavaDoc value) {
553         return fields.containsValue(value);
554     }
555
556     public boolean containsKey(Object JavaDoc key) {
557         return fields.containsKey(key);
558     }
559
560     public boolean isEmpty() {
561         return fields.isEmpty();
562     }
563
564     public int size() {
565         return fields.size();
566     }
567
568
569 } // end JahiaFieldSet
570
Popular Tags