KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > knowgate > hipergate > Category


1 /*
2   Copyright (C) 2003 Know Gate S.L. All rights reserved.
3                       C/Oña, 107 1º2 28050 Madrid (Spain)
4
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions
7   are met:
8
9   1. Redistributions of source code must retain the above copyright
10      notice, this list of conditions and the following disclaimer.
11
12   2. The end-user documentation included with the redistribution,
13      if any, must include the following acknowledgment:
14      "This product includes software parts from hipergate
15      (http://www.hipergate.org/)."
16      Alternately, this acknowledgment may appear in the software itself,
17      if and wherever such third-party acknowledgments normally appear.
18
19   3. The name hipergate must not be used to endorse or promote products
20      derived from this software without prior written permission.
21      Products derived from this software may not be called hipergate,
22      nor may hipergate appear in their name, without prior written
23      permission.
24
25   This library is distributed in the hope that it will be useful,
26   but WITHOUT ANY WARRANTY; without even the implied warranty of
27   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
28
29   You should have received a copy of hipergate License with this code;
30   if not, visit http://www.hipergate.org or mail to info@hipergate.org
31 */

32
33 package com.knowgate.hipergate;
34
35 import java.io.File JavaDoc;
36 import java.io.IOException JavaDoc;
37 import java.io.FileInputStream JavaDoc;
38
39 import java.util.Properties JavaDoc;
40
41 import java.util.LinkedList JavaDoc;
42 import java.util.ListIterator JavaDoc;
43 import java.util.NoSuchElementException JavaDoc;
44 import java.util.StringTokenizer JavaDoc;
45
46 import java.sql.Connection JavaDoc;
47 import java.sql.ResultSet JavaDoc;
48 import java.sql.Statement JavaDoc;
49 import java.sql.PreparedStatement JavaDoc;
50 import java.sql.CallableStatement JavaDoc;
51 import java.sql.SQLException JavaDoc;
52 import java.sql.DatabaseMetaData JavaDoc;
53
54 import com.knowgate.debug.DebugFile;
55 import com.knowgate.jdc.JDCConnection;
56 import com.knowgate.dataobjs.DB;
57 import com.knowgate.dataobjs.DBBind;
58 import com.knowgate.dataobjs.DBPersist;
59 import com.knowgate.dataobjs.DBSubset;
60
61 import com.knowgate.misc.Gadgets;
62 import com.knowgate.dfs.FileSystem;
63
64 /**
65  * Categories from k_categories database table
66  * @author Sergio Montoro Ten
67  * @version 2.2
68  */

69 public class Category extends DBPersist {
70
71   /**
72    * Create empty Category
73    */

74   public Category() {
75     super(DB.k_categories, "Category");
76     oFS = null;
77   }
78
79   // ----------------------------------------------------------
80

81   /**
82    * Create Category and set gu_category.
83    * @param sIdCategory Category GUID
84    * @throws SQLException
85    */

86   public Category(String JavaDoc sIdCategory) throws SQLException JavaDoc {
87     super(DB.k_categories,"Category");
88
89     put(DB.gu_category, sIdCategory);
90     oFS = null;
91   }
92
93   // ----------------------------------------------------------
94

95   /**
96    * Load Category from database
97    * @param oConn Database Connection
98    * @param sIdCategory Category GUID
99    * @throws SQLException
100    */

101   public Category(JDCConnection oConn, String JavaDoc sIdCategory) throws SQLException JavaDoc {
102     super(DB.k_categories,"Category");
103
104     Object JavaDoc aCatg[] = { sIdCategory };
105
106     load (oConn,aCatg);
107     oFS = null;
108   }
109
110   // ----------------------------------------------------------
111

112   protected Category(String JavaDoc sTableName, String JavaDoc sClassName) {
113     super(sTableName, sClassName);
114     oFS = null;
115   }
116
117   // ==========================================================
118

119   /**
120    * <p>Get a list of all parents or childs of a Category.</p>
121    * All levels up or down are scanned recursively.
122    * @param oConn Database Connection
123    * @param iDirection BROWSE_UP for browsing parents or BROWSE_DOWN for browsing childs.
124    * @param iOrder BROWSE_TOPDOWN first element on the list will be the top most parent,
125    * BROWSE_BOTTOMUP first element on the list will be the deepest child.
126    * @return LinkedList of Category objects.
127    * @throws SQLException
128    */

129   public LinkedList JavaDoc browse (JDCConnection oConn, int iDirection, int iOrder) throws SQLException JavaDoc {
130     String JavaDoc sCatId = getString(DB.gu_category);
131     String JavaDoc sNeighbour;
132     boolean bDoNext;
133     PreparedStatement JavaDoc oStmt;
134     ResultSet JavaDoc oRSet;
135     LinkedList JavaDoc oCatList = new LinkedList JavaDoc();
136     Category oCatg;
137
138     if (DebugFile.trace) {
139       DebugFile.writeln("Begin Category.browse([Connection], ...)");
140       DebugFile.incIdent();
141     }
142
143     if (iDirection==Category.BROWSE_UP) {
144       if (DebugFile.trace) DebugFile.writeln("Connection.prepareStatement(SELECT " + DB.gu_parent_cat + " FROM " + DB.k_cat_tree + " WHERE " + DB.gu_child_cat + "=?)");
145       oStmt = oConn.prepareStatement("SELECT " + DB.gu_parent_cat + " FROM " + DB.k_cat_tree + " WHERE " + DB.gu_child_cat + "=?", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
146     }
147     else {
148       if (DebugFile.trace) DebugFile.writeln("Connection.prepareStatement(SELECT " + DB.gu_child_cat + " FROM " + DB.k_cat_tree + " WHERE " + DB.gu_parent_cat + "=?)");
149       oStmt = oConn.prepareStatement("SELECT " + DB.gu_child_cat + " FROM " + DB.k_cat_tree + " WHERE " + DB.gu_parent_cat + "=?", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
150     }
151
152     do {
153
154       if (DebugFile.trace) DebugFile.writeln("PreparedStatement.setString(1, " + sCatId + ")");
155
156       oStmt.setString(1, sCatId);
157       oRSet = oStmt.executeQuery();
158       bDoNext = oRSet.next();
159
160       if (bDoNext)
161         sNeighbour = oRSet.getString(1);
162       else
163         sNeighbour = "";
164
165       oRSet.close();
166
167       if (bDoNext) {
168         if (sCatId.equals(sNeighbour)) {
169           bDoNext = false;
170         }
171         else {
172           oCatg = new Category(oConn, sNeighbour);
173
174           if (iDirection==Category.BROWSE_UP)
175             if (iOrder==Category.BROWSE_BOTTOMUP)
176               oCatList.addLast(oCatg);
177             else
178               oCatList.addFirst(oCatg);
179           else
180             if (iOrder==Category.BROWSE_BOTTOMUP)
181               oCatList.addFirst(oCatg);
182             else
183               oCatList.addLast(oCatg);
184
185           sCatId = sNeighbour;
186         } // fi(sCatId==sNeighbour)
187
} // fi (bDoNext)
188
} while (bDoNext);
189
190     oStmt.close();
191
192     if (DebugFile.trace) {
193       DebugFile.decIdent();
194       DebugFile.writeln("End Category.browse() : " + String.valueOf(oCatList.size()));
195     }
196
197     return oCatList;
198   } // browse
199

200   // ----------------------------------------------------------
201

202   /**
203    * <p>Compose a path to Category by concatenating all parents names.</p>
204    * Calls k_sp_get_cat_path.<br>
205    * Category parents are found and each parent name is extracted.<br>
206    * Then parent names are contenated in order separated by slash '/' characters.<br>
207    * This method is usefull when creating a physical directory path for files
208    * belonging to Products contained in a Category. This way the directory paths can
209    * mimmic the category tree structure.
210    * @param oConn Database Connection
211    * @return String with Category parent names concatenated with slash '/' characters.
212    * For example "ROOT/DOMAINS/SYSTEM/SYSTEM_APPS/SYSTEM_apps_webbuilder"
213    * @throws SQLException
214    */

215   public String JavaDoc getPath(Connection JavaDoc oConn) throws SQLException JavaDoc {
216     Statement JavaDoc oStmt;
217     ResultSet JavaDoc oRSet;
218     CallableStatement JavaDoc oCall;
219     DatabaseMetaData JavaDoc oMDat;
220     String JavaDoc sPath;
221     String JavaDoc sDBMS;
222
223     if (DebugFile.trace) {
224       DebugFile.writeln("Begin Category.getPath([Connection])" );
225       DebugFile.incIdent();
226       DebugFile.writeln("gu_category=" + get(DB.gu_category));
227     }
228
229     try {
230       oMDat = oConn.getMetaData();
231       if (null==oMDat)
232         sDBMS = "unknown";
233       else
234         sDBMS = oConn.getMetaData().getDatabaseProductName();
235     }
236     catch (NullPointerException JavaDoc npe) {
237       sDBMS = "unknown";
238     }
239
240       if (sDBMS.equals("PostgreSQL")) {
241         oStmt = oConn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
242
243         if (DebugFile.trace) DebugFile.writeln("Statement.executeQuery(SELECT k_sp_get_cat_path('" + getStringNull(DB.gu_category, "null") + "'))");
244
245         oRSet = oStmt.executeQuery("SELECT k_sp_get_cat_path ('" + getString(DB.gu_category) + "')");
246         oRSet.next();
247         sPath = oRSet.getString(1);
248         oRSet.close();
249         oStmt.close();
250       }
251       else {
252         if (DebugFile.trace) DebugFile.writeln("{call k_sp_get_cat_path ('" + getStringNull(DB.gu_category, "null") + "',?)}");
253
254         oCall = oConn.prepareCall("{call k_sp_get_cat_path (?,?)}");
255         oCall.setString(1, getString(DB.gu_category));
256         oCall.registerOutParameter(2, java.sql.Types.VARCHAR);
257         oCall.execute();
258         sPath = oCall.getString(2);
259         oCall.close();
260       }
261     // End SQLException
262

263     if (DebugFile.trace) {
264       DebugFile.decIdent();
265       DebugFile.writeln("End Category.getPath() : " + sPath);
266     }
267
268     return sPath;
269   } // getPath()
270

271   // ----------------------------------------------------------
272

273   /**
274    * <p>Delete Category and all its childs.</p>
275    * First delete all Products and Companies contained in Category, including
276    * physical disk files associted with Products and Company attachments.<br>
277    * Then call k_sp_del_category_r stored procedure and perform recursive
278    * deletion of all childs.
279    * @param oConn Database Connection
280    * @throws SQLException
281    */

282   public boolean delete(JDCConnection oConn) throws SQLException JavaDoc {
283     try {
284       return Category.delete(oConn, getString(DB.gu_category));
285     } catch (IOException JavaDoc ioe) {
286       throw new SQLException JavaDoc("IOException " + ioe.getMessage());
287     }
288   } // delete
289

290   // ----------------------------------------------------------
291

292   /**
293    * <p>Add object to Category.</p>
294    * The object GUID and numeric class identifier is inserted at k_x_cat_objs table.<br>
295    * @param oConn Database Connection
296    * @param sIdObject Object GUID
297    * @param iIdClass Object Numeric Class Identifier (variable ClassId)
298    * @param iAttribs Object attributes mask (user defined)
299    * @param iOdPosition Object Position. An arbitrary position for the object inside the
300    * category. Position is not unique for an object. Two or more objects may have the same
301    * position.
302    * @throws SQLException If object is alredy contanied in Category then a primary key violation exception is raised.
303    */

304   public int addObject(Connection JavaDoc oConn, String JavaDoc sIdObject, int iIdClass, int iAttribs, int iOdPosition) throws SQLException JavaDoc {
305      PreparedStatement JavaDoc oStmt;
306      int iRetVal;
307
308      if (DebugFile.trace) {
309        DebugFile.writeln("Begin Category.addObject([Connection], " + sIdObject + ", ...)" );
310        DebugFile.incIdent();
311      }
312
313      oStmt = oConn.prepareStatement("INSERT INTO " + DB.k_x_cat_objs + " (" + DB.gu_category + "," + DB.gu_object + "," + DB.id_class + "," + DB.bi_attribs + "," + DB.od_position + ") VALUES (?,?,?,?,?)");
314      oStmt.setString(1, getString(DB.gu_category));
315      oStmt.setString(2, sIdObject);
316      oStmt.setInt (3, iIdClass);
317      oStmt.setInt (4, iAttribs);
318      oStmt.setInt (5, iOdPosition);
319      iRetVal = oStmt.executeUpdate();
320      oStmt.close();
321
322      if (DebugFile.trace) {
323        DebugFile.decIdent();
324        DebugFile.writeln("End Category.addProduct() : " + iRetVal);
325      }
326
327      return iRetVal;
328   } // addProduct
329

330   // ----------------------------------------------------------
331

332   /**
333    * <p>Remove object from Category</p>
334    * Removing an object from a Category does not delete it.
335    * @param oConn Database Connection
336    * @param sIdObject Object GUID
337    * @return 1 if object was present at category, 0 if object was not present at category.
338    * @throws SQLException
339    */

340   public int removeObject(Connection JavaDoc oConn, String JavaDoc sIdObject) throws SQLException JavaDoc {
341      int iRetVal;
342      PreparedStatement JavaDoc oStmt = oConn.prepareStatement("DELETE FROM " + DB.k_x_cat_objs + " WHERE " + DB.gu_category + "=? AND " + DB.gu_object + "=?");
343      oStmt.setString(1, getString(DB.gu_category));
344      oStmt.setString(2, sIdObject);
345      iRetVal = oStmt.executeUpdate();
346      oStmt.close();
347      return iRetVal;
348   } // removeObject
349

350   // ----------------------------------------------------------
351

352   /**
353    * <p>Set group permissions.</p>
354    * Calls k_sp_cat_del_grp stored procedure.
355    * @param oConn Database Connection
356    * @param sIdGroups String of comma separated GUIDs of ACLGroups with permissions to remove.
357    * @param iRecurse Remove permissions also from childs Categories all levels down.
358    * @param iObjects Not Used, must be zero.
359    * @throws SQLException
360    */

361   public void removeGroupPermissions (Connection JavaDoc oConn, String JavaDoc sIdGroups, short iRecurse, short iObjects) throws SQLException JavaDoc {
362     CallableStatement JavaDoc oStmt;
363     StringTokenizer JavaDoc oUsrTok;
364     int iTokCount;
365     String JavaDoc sIdCategory;
366
367     if (DebugFile.trace) {
368        DebugFile.writeln("Begin Category.removeGroupPermissions([Connection], " + sIdGroups + "," + iRecurse + "," + iObjects + ")" );
369        DebugFile.incIdent();
370        DebugFile.writeln("Connection.prepareCall({ call k_sp_cat_del_grp ('" + getStringNull(DB.gu_category, "null") + "',?," + String.valueOf(iRecurse) + "," + String.valueOf(iObjects) + ") }");
371      }
372
373     if (oConn.getMetaData().getDatabaseProductName().equals("PostgreSQL"))
374       oStmt = oConn.prepareCall("{ call k_sp_cat_del_grp ('" + getString(DB.gu_category) + "',?,CAST(" + String.valueOf(iRecurse) + " AS SMALLINT), CAST(" + String.valueOf(iObjects) + " AS SMALLINT)) }");
375     else
376       oStmt = oConn.prepareCall("{ call k_sp_cat_del_grp ('" + getString(DB.gu_category) + "',?," + String.valueOf(iRecurse) + "," + String.valueOf(iObjects) + ") }");
377
378     if (sIdGroups.indexOf(',')>=0) {
379       oUsrTok = new StringTokenizer JavaDoc(sIdGroups, ",");
380       iTokCount = oUsrTok.countTokens();
381       sIdCategory = getString(DB.gu_category);
382
383       for (int t=0; t<iTokCount; t++) {
384         oStmt.setString(1, oUsrTok.nextToken());
385         oStmt.execute();
386       } // end for ()
387

388       oStmt.close();
389     }
390     else {
391       oStmt.setString(1, sIdGroups);
392       oStmt.execute();
393       oStmt.close();
394     }
395
396     if (DebugFile.trace) {
397        DebugFile.decIdent();
398        DebugFile.writeln("End Category.Category.removeGroupPermissions()");
399      }
400   } // removeGroupPermissions
401

402   // ----------------------------------------------------------
403

404   /**
405    * <p>Set group permissions for Category</p>
406    * Calls k_sp_cat_set_grp stored procedure.
407    * @param oConn Database Connection
408    * @param sIdGroups String of comma separated GUIDs of ACLGroups with permissions to set.
409    * @param iACLMask Permissions mask, any combination of { ACL.PERMISSION_LIST,
410    * ACL.PERMISSION_READ,ACL.PERMISSION_ADD,ACL.PERMISSION_DELETE,ACL.PERMISSION_MODIFY,
411    * ACL.PERMISSION_MODERATE,ACL.PERMISSION_SEND,ACL.PERMISSION_GRANT,
412    * ACL.PERMISSION_FULL_CONTROL }
413    * @param iRecurse Remove permissions also from childs Categories all levels down.
414    * @param iObjects Not Used, must be zero.
415    * @throws SQLException
416    * @see com.knowgate.acl.ACL
417    */

418   public void setGroupPermissions(Connection JavaDoc oConn, String JavaDoc sIdGroups, int iACLMask, short iRecurse, short iObjects) throws SQLException JavaDoc {
419     PreparedStatement JavaDoc oStmt;
420     CallableStatement JavaDoc oCall;
421     StringTokenizer JavaDoc oUsrTok;
422     String JavaDoc sToken;
423     int iTokCount;
424
425     if (DebugFile.trace) {
426        DebugFile.writeln("Begin Category.setGroupPermissions([Connection], " + sIdGroups + "," + iACLMask + "," + iRecurse + "," + iObjects + ")" );
427        DebugFile.incIdent();
428
429        DebugFile.writeln("database product name " + oConn.getMetaData().getDatabaseProductName());
430
431        if (oConn.getMetaData().getDatabaseProductName().equals("PostgreSQL"))
432          DebugFile.writeln("Connection.prepareStatement(SELECT k_sp_cat_set_grp ('" + getString(DB.gu_category) + "',?," + String.valueOf(iACLMask) + ", CAST(" + String.valueOf(iRecurse) + " AS SMALLINT), CAST(" + String.valueOf(iObjects) + " AS SMALLINT))");
433        else
434          DebugFile.writeln("Connection.prepareCall({ call k_sp_cat_set_grp ('" + getStringNull(DB.gu_category, "null") + "',?," + String.valueOf(iACLMask) + "," + String.valueOf(iRecurse) + "," + String.valueOf(iObjects) + ") }");
435      }
436
437     if (oConn.getMetaData().getDatabaseProductName().equals("PostgreSQL")) {
438       oStmt = oConn.prepareStatement("SELECT k_sp_cat_set_grp ('" + getString(DB.gu_category) + "',?," + String.valueOf(iACLMask) + ", CAST(" + String.valueOf(iRecurse) + " AS SMALLINT), CAST(" + String.valueOf(iObjects) + " AS SMALLINT))");
439       if (sIdGroups.indexOf(',')>0) {
440         oUsrTok = new StringTokenizer JavaDoc(sIdGroups, ",");
441         iTokCount = oUsrTok.countTokens();
442         for (int t=0; t<iTokCount; t++) {
443           oStmt.setString(1, oUsrTok.nextToken());
444           oStmt.execute();
445         } // end for ()
446
}
447       else {
448         oStmt.setString(1, sIdGroups);
449         oStmt.execute();
450       }
451       oStmt.close();
452     } else {
453       oCall = oConn.prepareCall("{ call k_sp_cat_set_grp ('" + getString(DB.gu_category) + "',?," + String.valueOf(iACLMask) + "," + String.valueOf(iRecurse) + "," + String.valueOf(iObjects) + ") }");
454       if (sIdGroups.indexOf(',')>0) {
455         oUsrTok = new StringTokenizer JavaDoc(sIdGroups, ",");
456         iTokCount = oUsrTok.countTokens();
457         for (int t=0; t<iTokCount; t++) {
458           sToken = oUsrTok.nextToken();
459           if (DebugFile.trace) DebugFile.writeln("CallableStatement.setString(1,"+sToken+")");
460           oCall.setString(1, sToken);
461           oCall.execute();
462         } // end for ()
463
}
464       else {
465         if (DebugFile.trace) DebugFile.writeln("CallableStatement.setString(1,"+sIdGroups+")");
466         oCall.setString(1, sIdGroups);
467         oCall.execute();
468       }
469       oCall.close();
470     }
471
472     if (DebugFile.trace) {
473        String JavaDoc[] aGrps = com.knowgate.misc.Gadgets.split(sIdGroups,',');
474        int iMsk;
475        for (int g=0; g<aGrps.length; g++) {
476          iMsk = getGroupPermissions(oConn,aGrps[g]);
477          if (iMsk!=iACLMask)
478            throw new SQLException JavaDoc("Procedure k_sp_cat_grp_perm returned a different permissions mask ("+String.valueOf(iMsk)+") for group "+aGrps[g]+" on category " + getStringNull(DB.gu_category,null)+ " than that set by k_sp_cat_set_grp ("+String.valueOf(iACLMask)+")");
479        }
480        DebugFile.decIdent();
481        DebugFile.writeln("End Category.Category.setGroupPermissions()");
482      }
483   } // setGroupPermissions
484

485   // ----------------------------------------------------------
486

487   /**
488    * <p>Get User permissions for Category</p>
489    * Calls k_sp_cat_usr_perm stored procedure.<br>
490    * User permissions are those granted directy to user plus those grants
491    * indirectly by assigning permisssion to a group witch the user belongs to.<br>
492    * Permissions are accumulative; a user gains new permissions by belonging to
493    * new groups. All permissions are of grant type, there are no deny permissions.
494    * @param oConn Database Connection
495    * @param sIdUser User GUID
496    * @return User permissions mask. Any combination of:
497    * { ACL.PERMISSION_LIST, ACL.PERMISSION_READ,ACL.PERMISSION_ADD,
498    * ACL.PERMISSION_DELETE,ACL.PERMISSION_MODIFY, ACL.PERMISSION_MODERATE,
499    * ACL.PERMISSION_SEND,ACL.PERMISSION_GRANT,ACL.PERMISSION_FULL_CONTROL }
500    * @throws SQLException
501    */

502   public int getUserPermissions(Connection JavaDoc oConn, String JavaDoc sIdUser) throws SQLException JavaDoc {
503     int iACLMask;
504     CallableStatement JavaDoc oCall;
505     Statement JavaDoc oStmt;
506     ResultSet JavaDoc oRSet;
507
508     if (DebugFile.trace) {
509        DebugFile.writeln("Begin Category.getUserPermissions([Connection], " + sIdUser + ")" );
510        DebugFile.incIdent();
511     }
512
513     if (oConn.getMetaData().getDatabaseProductName().equals("PostgreSQL")) {
514       oStmt = oConn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
515
516       if (DebugFile.trace) DebugFile.writeln("Statement.executeQuery(SELECT k_sp_cat_usr_perm ('" + sIdUser + "','" + getStringNull(DB.gu_category,"null") + "'))");
517
518       oRSet = oStmt.executeQuery("SELECT k_sp_cat_usr_perm ('" + sIdUser + "','" + getString(DB.gu_category) + "')");
519       oRSet.next();
520       iACLMask = oRSet.getInt(1);
521       oRSet.close();
522       oStmt.close();
523     }
524     else {
525       if (DebugFile.trace) DebugFile.writeln("Connection.prepareCall({ call k_sp_cat_usr_perm('" + sIdUser + "','" + getStringNull(DB.gu_category,null) + "',?) })");
526
527       oCall = oConn.prepareCall("{ call k_sp_cat_usr_perm(?,?,?) }");
528       oCall.setString(1, sIdUser);
529       oCall.setString(2, getString(DB.gu_category));
530       oCall.registerOutParameter(3, java.sql.Types.INTEGER);
531       oCall.execute();
532       iACLMask = oCall.getInt(3);
533       oCall.close();
534     }
535
536     if (DebugFile.trace) {
537        DebugFile.decIdent();
538        DebugFile.writeln("End Category.getUserPermissions() : " + String.valueOf(iACLMask));
539      }
540
541     return iACLMask;
542   } // getUserPermissions()
543

544   // ----------------------------------------------------------
545

546   /**
547    * <p>Get permissions mas of a group over this category</p>
548    * If there is no explicit permissions mask set at k_x_cat_group_acl for given
549    * group and this category, then the category hierarchy is scanned upwards and
550    * the permissions of the closest parent are assumed to be the ones of this category.
551    * If no parent has explicit permissions set for given group then return value is zero.
552    * @param oConn Database Connection
553    * @param sIdGroup ACLGroup GUID
554    * @return Group permissions mask. Any combination of:
555    * { ACL.PERMISSION_LIST, ACL.PERMISSION_READ,ACL.PERMISSION_ADD,
556    * ACL.PERMISSION_DELETE,ACL.PERMISSION_MODIFY, ACL.PERMISSION_MODERATE,
557    * ACL.PERMISSION_SEND,ACL.PERMISSION_GRANT,ACL.PERMISSION_FULL_CONTROL }
558    * @throws SQLException
559    * @since 3.0
560    */

561   public int getGroupPermissions(Connection JavaDoc oConn, String JavaDoc sIdGroup) throws SQLException JavaDoc {
562     int iACLMask;
563     CallableStatement JavaDoc oCall;
564     Statement JavaDoc oStmt;
565     ResultSet JavaDoc oRSet;
566
567     if (DebugFile.trace) {
568        DebugFile.writeln("Begin Category.getGroupPermissions([Connection], " + sIdGroup + ")" );
569        DebugFile.incIdent();
570     }
571
572     if (oConn.getMetaData().getDatabaseProductName().equals("PostgreSQL")) {
573       oStmt = oConn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
574
575       if (DebugFile.trace) DebugFile.writeln("Statement.executeQuery(SELECT k_sp_cat_grp_perm ('" + sIdGroup + "','" + getStringNull(DB.gu_category,"null") + "'))");
576
577       oRSet = oStmt.executeQuery("SELECT k_sp_cat_grp_perm ('" + sIdGroup + "','" + getString(DB.gu_category) + "')");
578       oRSet.next();
579       iACLMask = oRSet.getInt(1);
580       oRSet.close();
581       oStmt.close();
582     }
583     else {
584       if (DebugFile.trace) DebugFile.writeln("Connection.prepareCall({ call k_sp_cat_grp_perm('" + sIdGroup + "','" + getStringNull(DB.gu_category,null) + "',?) })");
585
586       oCall = oConn.prepareCall("{ call k_sp_cat_grp_perm(?,?,?) }");
587       oCall.setString(1, sIdGroup);
588       oCall.setString(2, getString(DB.gu_category));
589       oCall.registerOutParameter(3, java.sql.Types.INTEGER);
590       oCall.execute();
591       iACLMask = oCall.getInt(3);
592       oCall.close();
593     }
594
595     if (DebugFile.trace) {
596        DebugFile.decIdent();
597        DebugFile.writeln("End Category.getGroupPermissions() : " + String.valueOf(iACLMask));
598      }
599
600     return iACLMask;
601   } // getGroupPermissions()
602

603   // ----------------------------------------------------------
604

605   /**
606    * <p>Remove permissions for user at a Category.</p>
607    * Calls k_sp_cat_del_usr.<br>
608    * Only permissions directly granted to user are removed.<br>
609    * Permissions obtained by belonging to a Group remain active.<br>
610    * @param oConn Database Connection
611    * @param sIdUsers String of user GUIDs separated by commas.
612    * @param iRecurse Remove permissions from child categories.
613    * @param iObjects Not used, must be zero.
614    * @throws SQLException
615    */

616   public void removeUserPermissions(Connection JavaDoc oConn, String JavaDoc sIdUsers, short iRecurse, short iObjects) throws SQLException JavaDoc {
617     CallableStatement JavaDoc oStmt;
618     StringTokenizer JavaDoc oUsrTok;
619     int iTokCount;
620
621     if (DebugFile.trace) {
622        DebugFile.writeln("Begin Category.removeUserPermissions([Connection], " + sIdUsers + "," + iRecurse + "," + iObjects + ")" );
623        DebugFile.incIdent();
624        DebugFile.writeln("Connection.prepareCall({ call k_sp_cat_del_usr ('" + getStringNull(DB.gu_category, "null") + "',?," + String.valueOf(iRecurse) + "," + String.valueOf(iObjects) + ") }");
625      }
626
627     if (oConn.getMetaData().getDatabaseProductName().equals("PostgreSQL"))
628       oStmt = oConn.prepareCall("{ call k_sp_cat_del_usr ('" + getString(DB.gu_category) + "',?, CAST(" + String.valueOf(iRecurse) + " AS SMALLINT), CAST(" + String.valueOf(iObjects) + " AS SMALLINT)) }");
629     else
630       oStmt = oConn.prepareCall("{ call k_sp_cat_del_usr ('" + getString(DB.gu_category) + "',?," + String.valueOf(iRecurse) + "," + String.valueOf(iObjects) + ") }");
631
632     if (sIdUsers.indexOf(',')>=0) {
633       oUsrTok = new StringTokenizer JavaDoc(sIdUsers, ",");
634       iTokCount = oUsrTok.countTokens();
635
636       for (int t=0; t<iTokCount; t++) {
637         oStmt.setString(1, oUsrTok.nextToken());
638         oStmt.execute();
639       } // end for ()
640

641       oStmt.close();
642     }
643     else {
644       oStmt.setString(1, sIdUsers);
645       oStmt.execute();
646       oStmt.close();
647     }
648
649     if (DebugFile.trace) {
650        DebugFile.decIdent();
651        DebugFile.writeln("End Category.Category.removeUserPermissions()");
652      }
653   } // removeUserPermissions
654

655   // ----------------------------------------------------------
656

657   /**
658    * <p>Set user permissions for a Category.</p>
659    * Calls k_sp_cat_set_usr stored procedure.
660    * @param oConn Database Connection
661    * @param sIdUsers String of user GUIDs separated by commas.
662    * @param iACLMask Permissions mask. Any combination of:
663    * { ACL.PERMISSION_LIST, ACL.PERMISSION_READ,ACL.PERMISSION_ADD,
664    * ACL.PERMISSION_DELETE,ACL.PERMISSION_MODIFY, ACL.PERMISSION_MODERATE,
665    * ACL.PERMISSION_SEND,ACL.PERMISSION_GRANT,ACL.PERMISSION_FULL_CONTROL }
666    * @param iRecurse Remove permissions from child categories.
667    * @param iObjects Not used, must be zero.
668    * @throws SQLException
669    */

670   public void setUserPermissions(Connection JavaDoc oConn, String JavaDoc sIdUsers, int iACLMask, short iRecurse, short iObjects) throws SQLException JavaDoc {
671     CallableStatement JavaDoc oStmt;
672     StringTokenizer JavaDoc oUsrTok;
673     String JavaDoc sSQL;
674     String JavaDoc sUserId;
675     int iTokCount;
676
677     if (DebugFile.trace) {
678        DebugFile.writeln("Begin Category.setUserPermissions([Connection], " + sIdUsers + "," + iACLMask + "," + iRecurse + "," + iObjects + ")" );
679        DebugFile.incIdent();
680        DebugFile.writeln(" " + DB.gu_category + "=" + getStringNull(DB.gu_category, "null"));
681      }
682
683     if (oConn.getMetaData().getDatabaseProductName().equals("PostgreSQL"))
684       sSQL = "{ call k_sp_cat_set_usr (?,?," + String.valueOf(iACLMask) + ", CAST(" + String.valueOf(iRecurse) + " AS SMALLINT), CAST(" + String.valueOf(iObjects) + " AS SMALLINT)) }";
685     else
686       sSQL = "{ call k_sp_cat_set_usr (?,?," + String.valueOf(iACLMask) + "," + String.valueOf(iRecurse) + "," + String.valueOf(iObjects) + ") }";
687
688     if (DebugFile.trace) DebugFile.writeln("Connection.prepareCall(" + sSQL + ")");
689
690     oStmt = oConn.prepareCall(sSQL);
691
692     if (sIdUsers.indexOf(',')>0) {
693       oUsrTok = new StringTokenizer JavaDoc(sIdUsers, ",");
694       iTokCount = oUsrTok.countTokens();
695
696       for (int t=0; t<iTokCount; t++) {
697         sUserId = oUsrTok.nextToken();
698
699         if (DebugFile.trace) DebugFile.writeln("binding user " + String.valueOf(t+1) + " " + sUserId);
700
701         oStmt.setObject(1, getString(DB.gu_category), java.sql.Types.CHAR);
702         oStmt.setObject(2, sUserId, java.sql.Types.CHAR);
703         oStmt.execute();
704       } // end for ()
705

706     }
707     else {
708       if (DebugFile.trace) DebugFile.writeln("binding user " + sIdUsers);
709
710       oStmt.setObject(1, getString(DB.gu_category), java.sql.Types.CHAR);
711       oStmt.setObject(2, sIdUsers, java.sql.Types.CHAR);
712       oStmt.execute();
713     }
714
715     oStmt.close();
716
717     if (DebugFile.trace) {
718        DebugFile.decIdent();
719        DebugFile.writeln("End Category.setUserPermissions()");
720      }
721   } // setUserPermissions
722

723   // ----------------------------------------------------------
724

725   /**
726    * <p>Inherits permissions from another Category.</p>
727    * All previous permissions on this Category are removed before copying
728    * permission from the other Category.
729    * @param oConn Database Connection
730    * @param sFromCategory GUID of category with permissions to be inherited.
731    * @param iRecurse Propagate permissions to child categories.
732    * @param iObjects Not used, must be zero.
733    * @throws SQLException
734    */

735   public void inheritPermissions(JDCConnection oConn, String JavaDoc sFromCategory, short iRecurse, short iObjects) throws SQLException JavaDoc {
736     int i;
737     int iUsrPerms;
738     int iGrpPerms;
739     String JavaDoc sIdCategory = getString(DB.gu_category);
740     DBSubset oUsrPerms = new DBSubset(DB.k_x_cat_user_acl, DB.gu_user + "," + DB.acl_mask, DB.gu_category + "='" + sFromCategory + "'", 100);
741     DBSubset oGrpPerms = new DBSubset(DB.k_x_cat_group_acl, DB.gu_acl_group + "," + DB.acl_mask, DB.gu_category + "='" + sFromCategory + "'", 100);
742     Statement JavaDoc oDelete = oConn.createStatement();
743     PreparedStatement JavaDoc oInsert;
744
745     if (DebugFile.trace) {
746        DebugFile.writeln("Begin Category.inheritPermissions([Connection], " + sFromCategory + "," + iRecurse + "," + iObjects + ")" );
747        DebugFile.incIdent();
748      }
749
750     if (DebugFile.trace) DebugFile.writeln(" loading user permissions from " + DB.k_x_cat_user_acl);
751
752     iUsrPerms = oUsrPerms.load(oConn);
753
754     if (DebugFile.trace) DebugFile.writeln(" loading group permissions from " + DB.k_x_cat_group_acl);
755
756     iGrpPerms = oGrpPerms.load(oConn);
757
758     if (DebugFile.trace) DebugFile.writeln(" Connection.executeUpdate(" + "DELETE FROM " + DB.k_x_cat_user_acl + " WHERE " + DB.gu_category + "='" + sIdCategory + "')");
759
760     oDelete.executeUpdate("DELETE FROM " + DB.k_x_cat_user_acl + " WHERE " + DB.gu_category + "='" + sIdCategory + "'");
761
762     if (DebugFile.trace) DebugFile.writeln(" Connection.executeUpdate(" + "DELETE FROM " + DB.k_x_cat_group_acl + " WHERE " + DB.gu_category + "='" + sIdCategory + "')");
763
764     oDelete.executeUpdate("DELETE FROM " + DB.k_x_cat_group_acl + " WHERE " + DB.gu_category + "='" + sIdCategory + "'");
765
766     oDelete.close();
767     oDelete = null;
768
769     if (DebugFile.trace) DebugFile.writeln(" Connection.prepareStatement(" + "INSERT INTO " + DB.k_x_cat_user_acl + "(" + DB.gu_category + "," + DB.gu_user + "," + DB.acl_mask + ") VALUES (?,?,?))");
770
771     oInsert = oConn.prepareStatement("INSERT INTO " + DB.k_x_cat_user_acl + "(" + DB.gu_category + "," + DB.gu_user + "," + DB.acl_mask + ") VALUES (?,?,?)");
772
773     for (i=0; i<iUsrPerms; i++) {
774       oInsert.setString(1, sIdCategory );
775       oInsert.setString(2, oUsrPerms.getString(0,i) );
776       oInsert.setInt(3, oUsrPerms.getInt(1,i) );
777
778       if (DebugFile.trace) DebugFile.writeln(" PreparedStatement.executeUpdate(" + sIdCategory + "," + oUsrPerms.getString(0,i) + "," + oUsrPerms.getInt(1,i) + ")");
779       oInsert.executeUpdate();
780       oInsert.close();
781     }
782
783     if (DebugFile.trace) DebugFile.writeln(" Connection.prepareStatement(" + "INSERT INTO " + DB.k_x_cat_group_acl + "(" + DB.gu_category + "," + DB.gu_acl_group + "," + DB.acl_mask + ") VALUES (?,?,?))");
784
785     oInsert = oConn.prepareStatement("INSERT INTO " + DB.k_x_cat_group_acl + "(" + DB.gu_category + "," + DB.gu_acl_group + "," + DB.acl_mask + ") VALUES (?,?,?)");
786     for (i=0; i<iGrpPerms; i++) {
787       oInsert.setString(1, sIdCategory );
788       oInsert.setString(2, oGrpPerms.getString(0,i) );
789       oInsert.setInt(3, oGrpPerms.getInt(1,i) );
790
791       if (DebugFile.trace) DebugFile.writeln(" PreparedStatement.executeUpdate(" + sIdCategory + "," + oGrpPerms.getString(0,i) + "," + oGrpPerms.getInt(1,i) + ")");
792       oInsert.executeUpdate();
793       oInsert.close();
794     }
795
796     if (DebugFile.trace) {
797        DebugFile.decIdent();
798        DebugFile.writeln("End Category.inheritPermissions()");
799      }
800   } // inheritPermissions
801

802   // ----------------------------------------------------------
803

804   /**
805    * Get whether or not this category descends at any level from another one.
806    * @param oConn Database Connection
807    * @param sParentCategory Parent category
808    * @return <b>true</b> if this category descends at any level of depth from sParentCategory.
809    * @throws SQLException
810    */

811   public boolean isChildOf(Connection JavaDoc oConn, String JavaDoc sParentCategory) throws SQLException JavaDoc {
812     String JavaDoc sSelfId = getString(DB.gu_category);
813     String JavaDoc sChild;
814     boolean isChild = false;
815     boolean bDoNext;
816     PreparedStatement JavaDoc oStmt = oConn.prepareStatement("SELECT " + DB.gu_child_cat + " FROM " + DB.k_cat_tree + " WHERE " + DB.gu_parent_cat + "=?", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
817     ResultSet JavaDoc oRSet;
818
819     do {
820       oStmt.setString(1, sParentCategory);
821       oRSet = oStmt.executeQuery();
822       bDoNext = oRSet.next();
823       if (bDoNext)
824         sChild = oRSet.getString(1);
825       else
826         sChild = "-1";
827       oRSet.close();
828
829       if (bDoNext) {
830         if (sChild.equals(sParentCategory)) {
831           bDoNext = false;
832         }
833         else if (sChild.equals(sSelfId)) {
834           isChild = true;
835           bDoNext = false;
836         }
837         else {
838           sParentCategory = sChild;
839         }
840       } // endif (bDoNext)
841
} while (bDoNext);
842
843     oStmt.close();
844
845     return isChild;
846   } // isChildOf
847

848   // ----------------------------------------------------------
849

850   /**
851    * Get whether or not this category is parent at any level of another one.
852    * @param oConn Database Connection
853    * @param sChildCategory Child Category GUID
854    * @return <b>true</b> if this category is parent at any level.
855    * @throws SQLException
856    */

857   public boolean isParentOf(Connection JavaDoc oConn, String JavaDoc sChildCategory) throws SQLException JavaDoc {
858     String JavaDoc sSelfId;
859     String JavaDoc sParnt;
860     boolean isParent = false;
861     boolean bDoNext;
862     PreparedStatement JavaDoc oStmt = oConn.prepareStatement("SELECT " + DB.gu_parent_cat + " FROM " + DB.k_cat_tree + " WHERE " + DB.gu_child_cat + "=?", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
863     ResultSet JavaDoc oRSet;
864
865     if (DebugFile.trace) {
866        DebugFile.writeln("Begin Category.isParentOf(" + sChildCategory + ")");
867        DebugFile.incIdent();
868     }
869
870     sSelfId = getString(DB.gu_category);
871
872     if (DebugFile.trace) DebugFile.writeln(" " + DB.gu_category + " = " + sSelfId);
873
874     do {
875       oStmt.setString(1, sChildCategory);
876       oRSet = oStmt.executeQuery();
877       bDoNext = oRSet.next();
878       if (bDoNext)
879         sParnt = oRSet.getString(1);
880       else
881         sParnt = "-1";
882       oRSet.close();
883
884       if (DebugFile.trace) DebugFile.writeln(" id_parent = " + sParnt);
885
886       if (bDoNext) {
887         if (sParnt.equals(sChildCategory)) {
888           bDoNext = false;
889         }
890         else if (sParnt.equals(sSelfId)) {
891           isParent = true;
892           bDoNext = false;
893         }
894         else {
895           sChildCategory = sParnt;
896         }
897       } // endif (bDoNext)
898
} while (bDoNext);
899
900     oStmt.close();
901
902     if (DebugFile.trace) {
903        DebugFile.decIdent();
904        DebugFile.writeln("End Category.isParentOf() : " + isParent);
905      }
906
907     return isParent;
908   } // isParentOf
909

910   // ----------------------------------------------------------
911

912   /**
913    * <p>Get category depth level.</p>
914    * Calls k_sp_cat_level stored procedure.<br>
915    * Root Categories have level 1.
916    * @param oConn Database Connection
917    * @return Category depth evel starting at 1.
918    * @throws SQLException
919    */

920   public int level(JDCConnection oConn) throws SQLException JavaDoc {
921     int iLevel;
922     CallableStatement JavaDoc oCall;
923     Statement JavaDoc oStmt;
924     ResultSet JavaDoc oRSet;
925
926     if (oConn.getDataBaseProduct()==JDCConnection.DBMS_POSTGRESQL) {
927       oStmt = oConn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
928       oRSet = oStmt.executeQuery("SELECT k_sp_cat_level('" + getString(DB.gu_category) + "')");
929       oRSet.next();
930       iLevel = oRSet.getInt(1);
931       oRSet.close();
932       oStmt.close();
933     }
934     else {
935       oCall = oConn.prepareCall("{ call k_sp_cat_level(?,?)}");
936       oCall.setString(1, getString(DB.gu_category));
937       oCall.registerOutParameter(2, java.sql.Types.INTEGER);
938       oCall.execute();
939       iLevel = oCall.getInt(2);
940       oCall.close();
941     }
942
943     return iLevel;
944   } // level
945

946   // ----------------------------------------------------------
947

948   /**
949    * @param oConn Database Connection
950    * @return <b>true</b> if Category is present at k_cat_root table.
951    * @throws SQLException
952    */

953   public boolean getIsRoot(Connection JavaDoc oConn) throws SQLException JavaDoc {
954     Statement JavaDoc oStmt;
955     ResultSet JavaDoc oRSet;
956     boolean bRoot = false;
957
958     // Begin SQLException
959
oStmt = oConn.createStatement();
960       oRSet = oStmt.executeQuery("SELECT " + DB.gu_category + " FROM " + DB.k_cat_root + " WHERE " + DB.gu_category + "='" + getString(DB.gu_category) + "'");
961
962       bRoot = oRSet.next();
963
964       oRSet.close();
965       oStmt.close();
966     // End SQLException
967

968     return bRoot;
969   } // getIsRoot
970

971   // ----------------------------------------------------------
972

973   /**
974    * Make or unmake a root category.
975    * @param oConn Database Connection
976    * @param bIsRoot <b>true</b> if category is to be made root.
977    * @throws SQLException If This Category is present as a child of another
978    * category at k_cat_tree table.
979    */

980   public void setIsRoot(Connection JavaDoc oConn, boolean bIsRoot) throws SQLException JavaDoc {
981     Statement JavaDoc oStmt;
982     ResultSet JavaDoc oRSet;
983     boolean bIsChild;
984
985     if (DebugFile.trace) {
986       DebugFile.writeln("Begin Category.setIsRoot([Connection], " + String.valueOf(bIsRoot) + ")" );
987       DebugFile.incIdent();
988       }
989
990     // Begin SQLException
991
if (bIsRoot) {
992         oStmt = oConn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
993         if (DebugFile.trace) DebugFile.writeln("Statement.executeQuery(SELECT NULL FROM " + DB.k_cat_tree + " WHERE " + DB.gu_child_cat + "='" + getStringNull(DB.gu_category,"null") + "')");
994         oRSet = oStmt.executeQuery("SELECT NULL FROM " + DB.k_cat_tree + " WHERE " + DB.gu_child_cat + "='" + getString(DB.gu_category) + "'");
995         bIsChild = oRSet.next();
996         oRSet.close();
997         oStmt.close();
998
999         if (bIsChild)
1000          throw new SQLException JavaDoc("Category cannot be set Root if present as a child at k_cat_tree table");
1001      }
1002
1003      oStmt = oConn.createStatement();
1004
1005      if (DebugFile.trace) DebugFile.writeln("Statement.executeUpdate(DELETE FROM " + DB.k_cat_root + " WHERE " + DB.gu_category + "='" + getStringNull(DB.gu_category, "null") + "')");
1006
1007      oStmt.executeUpdate("DELETE FROM " + DB.k_cat_root + " WHERE " + DB.gu_category + "='" + getString(DB.gu_category) + "'");
1008
1009      if (bIsRoot) {
1010        if (DebugFile.trace) DebugFile.writeln("Statement.executeUpdate(INSERT INTO " + DB.k_cat_root + "(" + DB.gu_category + ") VALUES ('" + getStringNull(DB.gu_category, "null") + "')");
1011
1012        oStmt.executeUpdate("INSERT INTO " + DB.k_cat_root + "(" + DB.gu_category + ") VALUES ('" + getString(DB.gu_category) + "')");
1013      }
1014
1015      oStmt.close();
1016    // End SQLException
1017

1018    if (DebugFile.trace) {
1019      DebugFile.decIdent();
1020      DebugFile.writeln("End Category.setIsRoot()");
1021      }
1022  } // setIsRoot
1023

1024  // ----------------------------------------------------------
1025
/**
1026   * Get translated label for a category.
1027   * @param oConn Database Connection
1028   * @param sLanguage Language code from k_lu_languages table.
1029   * @return Translated label or <b>null</b> if no translated label for such
1030   * language was found at k_cat_labels table.
1031   * @throws SQLException
1032   */

1033  public String JavaDoc getLabel(Connection JavaDoc oConn, String JavaDoc sLanguage) throws SQLException JavaDoc {
1034    String JavaDoc sTr;
1035
1036    if (DebugFile.trace) {
1037      DebugFile.writeln("Begin Category.getLabel([Connection], " + sLanguage + ")" );
1038      DebugFile.incIdent();
1039      DebugFile.writeln("Connection.prepareStatement(SELECT " + DB.tr_category + " FROM " + DB.k_cat_labels + " WHERE " + DB.gu_category + "='" + get(DB.gu_category) + "' AND " + DB.id_language + "='" + sLanguage + "'");
1040      }
1041
1042    PreparedStatement JavaDoc oStmt = oConn.prepareStatement("SELECT " + DB.tr_category + " FROM " + DB.k_cat_labels + " WHERE " + DB.gu_category + "=? AND " + DB.id_language + "=?", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
1043    oStmt.setString(1, getString(DB.gu_category));
1044    oStmt.setString(2, sLanguage);
1045
1046    ResultSet JavaDoc oRSet = oStmt.executeQuery();
1047    if (oRSet.next())
1048      sTr = oRSet.getString(1);
1049    else
1050      sTr = null;
1051    oRSet.close();
1052    oStmt.close();
1053
1054    if (DebugFile.trace) {
1055      DebugFile.decIdent();
1056      DebugFile.writeln("End Category.getLabel() : " + sTr);
1057    }
1058
1059    return sTr;
1060  } // getLabel()
1061

1062  // ----------------------------------------------------------
1063

1064  /**
1065   * <p>Get Category translated labels as a DBSubset.</p>
1066   * @param oConn Database Connection
1067   * @return DBSubset with columns:<br>
1068   * <table border=1 cellpadding=4>
1069   * <tr><td><b>id_language</b></td><td><b>tr_category</b></td><td><b>url_category</b></td></tr>
1070   * <tr><td>2 chras. Lang. Id.</td><td>Translated Category Name</td><td>URL for Category</td></tr>
1071   * </table>
1072   * @throws SQLException
1073   */

1074  public DBSubset getNames(JDCConnection oConn) throws SQLException JavaDoc {
1075    Object JavaDoc aCatg[] = { get(DB.gu_category) };
1076
1077    oNames = new DBSubset(DB.k_cat_labels, DB.id_language + "," + DB.tr_category + "," + DB.url_category, DB.gu_category + "=?", 4);
1078    oNames.load (oConn, aCatg);
1079
1080    return oNames;
1081  } // getNames
1082

1083  // ----------------------------------------------------------
1084

1085  /**
1086   * <p>Get first level childs as a DBSubset.</p>
1087   * @param oConn Database Connection
1088   * @return Single column DBSubset with child GUIDs
1089   * @throws SQLException
1090   */

1091  public DBSubset getChilds(JDCConnection oConn) throws SQLException JavaDoc {
1092    Object JavaDoc aCatg[] = { get(DB.gu_category) };
1093
1094    oChilds = new DBSubset(DB.k_cat_tree, DB.gu_child_cat, DB.gu_parent_cat + "=?",1);
1095
1096    oChilds.load (oConn, aCatg);
1097
1098    return oChilds;
1099  } // getChilds
1100

1101  // ----------------------------------------------------------
1102

1103  /**
1104   * <p>Get inmediate parents as a DBSubset.</p>
1105   * @param oConn Database Connection
1106   * @return Single column DBSubset with parent GUIDs
1107   * @throws SQLException
1108   */

1109  public DBSubset getParents(JDCConnection oConn) throws SQLException JavaDoc {
1110    Object JavaDoc aCatg[] = { get(DB.gu_category) };
1111
1112    oParents = new DBSubset(DB.k_cat_tree, DB.gu_parent_cat, DB.gu_child_cat + "=?", 1);
1113    oParents.load (oConn, aCatg);
1114
1115    return oParents;
1116  } // getParents
1117

1118  // ----------------------------------------------------------
1119

1120  /**
1121   * Get objects contained at Category.
1122   * @param oConn Database Connection
1123   * @return DBSubset with columns:
1124   * <table border=1 cellpadding=4>
1125   * <tr><td><b>gu_object</b></td><td><b>id_class</b></td><td><b>bi_attribs</b></td></tr>
1126   * </table>
1127   * @throws SQLException
1128   */

1129  public DBSubset getObjects(JDCConnection oConn) throws SQLException JavaDoc {
1130    Object JavaDoc aCatg[] = { get(DB.gu_category) };
1131    DBSubset oObjs;
1132
1133    oObjs = new DBSubset(DB.k_x_cat_objs, DB.gu_object + "," + DB.id_class + "," + DB.bi_attribs, DB.gu_category + "=? ORDER BY " + DB.od_position, 64);
1134
1135    oObjs.load(oConn, new Object JavaDoc[]{getString(DB.gu_category)});
1136
1137    return oObjs;
1138  } // getObjects
1139

1140  // ----------------------------------------------------------
1141

1142  /**
1143   * Get Groups with permissions over this Category.
1144   * @param oConn Database Connection
1145   * @return A DBSubset with 2 columns: gu_acl_group, acl_mask
1146   * @throws SQLException
1147   */

1148  public DBSubset getACLGroups(JDCConnection oConn) throws SQLException JavaDoc {
1149    Object JavaDoc aCatg[] = { get(DB.gu_category) };
1150
1151    oACLGroups = new DBSubset(DB.k_x_cat_group_acl, DB.gu_acl_group + "," + DB.acl_mask, DB.gu_category + "=?", 50);
1152    oACLGroups.load (oConn, aCatg);
1153
1154    return oACLGroups;
1155  } // getACLGroups
1156

1157  // ----------------------------------------------------------
1158

1159  /**
1160   * Get Users with direct permissions over this Category.
1161   * @param oConn Database Connection
1162   * @return A DBSubset with 2 columns: gu_user, acl_mask
1163   * @throws SQLException
1164   */

1165  public DBSubset getACLUsers(JDCConnection oConn) throws SQLException JavaDoc {
1166    Object JavaDoc aCatg[] = { get("id_category") };
1167
1168    oACLUsers = new DBSubset(DB.k_x_cat_user_acl, DB.gu_user + "," + DB.acl_mask, DB.gu_category + "=?", 100);
1169    oACLUsers.load (oConn, aCatg);
1170
1171    return oACLUsers;
1172  } // getACLUsers
1173

1174  // ----------------------------------------------------------
1175

1176  /**
1177   * <p>Set New Parent for this category.</p>
1178   * The old parent (if any) is not changed nor removed.<br>
1179   * If Category is already a child of selected parent method proceeds silently
1180   * and no error is raised.
1181   * @param oConn Database Connection
1182   * @param sIdParent GUID of parent Category
1183   * @throws SQLException
1184   */

1185  public void setParent(Connection JavaDoc oConn, String JavaDoc sIdParent) throws SQLException JavaDoc {
1186    Statement JavaDoc oStmt = oConn.createStatement();
1187    ResultSet JavaDoc oRSet;
1188    String JavaDoc sSQL;
1189    boolean bAlreadyExists;
1190
1191    if (DebugFile.trace) {
1192      DebugFile.writeln("Begin Category.setParent([Connection], " + sIdParent + ")" );
1193      DebugFile.incIdent();
1194      }
1195
1196    oStmt = oConn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
1197    sSQL = "SELECT NULL FROM " + DB.k_cat_tree + " WHERE " + DB.gu_parent_cat + "='" + sIdParent + "' AND " + DB.gu_child_cat + "='" + getString(DB.gu_category) + "'";
1198    if (DebugFile.trace) DebugFile.writeln("Statement.executeQuery(" + sSQL + ")");
1199    oRSet = oStmt.executeQuery(sSQL);
1200    bAlreadyExists = oRSet.next();
1201    oRSet.close();
1202    oStmt.close();
1203
1204    if (!bAlreadyExists) {
1205      oStmt = oConn.createStatement();
1206      sSQL = "INSERT INTO " + DB.k_cat_tree + " (" + DB.gu_parent_cat + "," + DB.gu_child_cat + ") VALUES ('" + sIdParent + "','" + getString(DB.gu_category) + "')";
1207      if (DebugFile.trace) DebugFile.writeln("Statement.execute(" + sSQL + ")");
1208      oStmt.execute(sSQL);
1209      oStmt.close();
1210    }
1211    if (DebugFile.trace) {
1212      DebugFile.decIdent();
1213      DebugFile.writeln("End Category.setParent()");
1214      }
1215  } // setParent
1216

1217  // ----------------------------------------------------------
1218

1219  /**
1220   * <p>Remove Category from parent.</p>
1221   * Removing a Category from a parent does not delete it.
1222   * @param oConn Database Connection
1223   * @param sIdParent Parent Category GUID
1224   * @throws SQLException
1225   */

1226  public void resetParent(Connection JavaDoc oConn, String JavaDoc sIdParent) throws SQLException JavaDoc {
1227    Statement JavaDoc oStmt = oConn.createStatement();
1228    String JavaDoc sSQL;
1229
1230    if (DebugFile.trace) {
1231      DebugFile.writeln("Begin Category.resetParent([Connection], " + sIdParent + ")" );
1232      DebugFile.incIdent();
1233      }
1234
1235    sSQL = "DELETE FROM " + DB.k_cat_tree + " WHERE " + DB.gu_parent_cat + "='" + sIdParent + "' AND " + DB.gu_child_cat + "='" + getString(DB.gu_category) + "'";
1236
1237    if (DebugFile.trace) DebugFile.writeln("oStmt.executeUpdate(" + sSQL + ")");
1238
1239    oStmt.executeUpdate(sSQL);
1240
1241    if (DebugFile.trace) {
1242      DebugFile.decIdent();
1243      DebugFile.writeln("End Category.resetParent()");
1244      }
1245  } // resetParent
1246

1247  // ----------------------------------------------------------
1248

1249  /**
1250   * <p>Store Category.</p>
1251   * If gu_category is null a new GUID is automatically assigned.<br>
1252   * dt_modified field is set to current date.
1253   * @param oConn Database Connection
1254   * @throws SQLException
1255   */

1256  public boolean store(JDCConnection oConn) throws SQLException JavaDoc {
1257    java.sql.Timestamp JavaDoc dtNow = new java.sql.Timestamp JavaDoc(DBBind.getTime());
1258
1259    // Si no se especificó un identificador para la categoria
1260
// entonces añadirlo autimaticamente
1261
if (!AllVals.containsKey(DB.gu_category))
1262      put(DB.gu_category, Gadgets.generateUUID());
1263
1264    // Forzar la fecha de modificación del registro
1265
replace(DB.dt_modified, dtNow);
1266
1267    return super.store(oConn);
1268  } // store
1269

1270  // ----------------------------------------------------------
1271

1272  /**
1273   * <p>Expand all Category childs.</p>
1274   * Calls k_sp_cat_expand stored procedure.<br>
1275   * Expansion tree is stored at k_cat_expand table.
1276   * @param oConn Database Connection
1277   * @throws SQLException
1278   */

1279  public void expand(Connection JavaDoc oConn) throws SQLException JavaDoc {
1280    CallableStatement JavaDoc oStmt;
1281
1282    if (DebugFile.trace) {
1283      DebugFile.writeln("Begin Category.expand([Connection])");
1284      DebugFile.incIdent();
1285      DebugFile.writeln("Connection.prepareCall({ call k_sp_cat_expand ('" + getStringNull(DB.gu_category,"null") + "')}");
1286    }
1287
1288    oStmt = oConn.prepareCall("{ call k_sp_cat_expand ('" + getString(DB.gu_category) + "') }");
1289    oStmt.execute();
1290    oStmt.close();
1291
1292    if (DebugFile.trace) {
1293      DebugFile.decIdent();
1294      DebugFile.writeln("End Category.expand()");
1295    }
1296  } // expand()
1297

1298  // ----------------------------------------------------------
1299

1300  /**
1301   * <p>Store a set of labels for this category</p>
1302   * This method takes a string of the form "en;Root|es;Raíz|fr;Racine|it;Radice|ru;??????"
1303   * and store one label for each {language,literal} pair
1304   * @param oConn JDCConnection
1305   * @param sNamesTable String Language names and translated names
1306   * @param sRowDelim String Delimiter for {language,literal} pairs,
1307   * in the example above it would be "|"
1308   * @param sColDelim String Delimiter between language and literal,
1309   * in the example above it would be ";"
1310   * @throws SQLException
1311   * @throws NoSuchElementException
1312   */

1313  public void storeLabels(JDCConnection oConn, String JavaDoc sNamesTable,
1314                          String JavaDoc sRowDelim, String JavaDoc sColDelim)
1315      throws SQLException JavaDoc, NoSuchElementException JavaDoc {
1316    String JavaDoc sName;
1317    String JavaDoc sLanguageId;
1318    String JavaDoc sTrCategory;
1319    int iTokCount;
1320    StringTokenizer JavaDoc oRowTok;
1321    StringTokenizer JavaDoc oColTok;
1322    CategoryLabel oName = new CategoryLabel();
1323
1324    if (DebugFile.trace) {
1325      DebugFile.writeln("Begin Category.storeLabels([Connection], \"" + sNamesTable + "\",\"" + sRowDelim + "\",\"" + sColDelim + "\")");
1326      DebugFile.incIdent();
1327    }
1328
1329    if (sNamesTable.length()>0) {
1330      oName.put (DB.gu_category, getString(DB.gu_category));
1331
1332      // Sacar el idioma y la lista de etiquetas del String recibido como parametro.
1333

1334      if (DebugFile.trace) DebugFile.writeln("new StringTokenizer(" + sNamesTable + "\"" + sRowDelim + "\"");
1335
1336      oRowTok = new StringTokenizer JavaDoc(sNamesTable, sRowDelim);
1337
1338      iTokCount = oRowTok.countTokens();
1339
1340      if (DebugFile.trace) DebugFile.writeln(String.valueOf(iTokCount) + " tokens found");
1341
1342      for (int r=0; r<iTokCount; r++) {
1343        // Separar los registros
1344
sName = oRowTok.nextToken();
1345
1346        if (DebugFile.trace) DebugFile.writeln("new StringTokenizer(" + sName + ", \"" + sColDelim + "\"");
1347
1348        // Para cada registro separar los campos
1349
oColTok = new StringTokenizer JavaDoc(sName, sColDelim);
1350
1351        if (DebugFile.trace) DebugFile.writeln("StringTokenizer.nextToken(" + String.valueOf(r) + ") for id_language");
1352
1353        sLanguageId = oColTok.nextToken();
1354
1355        if (DebugFile.trace) DebugFile.writeln("StringTokenizer.nextToken(" + String.valueOf(r) + ") for tr_category");
1356
1357        sTrCategory = oColTok.nextToken();
1358
1359        if (sTrCategory!=null) {
1360          sTrCategory = sTrCategory.trim();
1361
1362          if (sTrCategory.length()>0) {
1363            oName.replace(DB.id_language, sLanguageId);
1364            oName.replace(DB.tr_category, sTrCategory);
1365
1366            if (DebugFile.trace) DebugFile.writeln("CategoryLabel.store("+ sLanguageId + "," + sTrCategory + ")");
1367
1368            oName.store(oConn);
1369          }
1370        } // fi (tr_category!=null)
1371
} // endfor (r)
1372
} // fi (sNamesTable!="")
1373

1374    if (DebugFile.trace) {
1375      DebugFile.decIdent();
1376      DebugFile.writeln("End Category.storeLabels()");
1377    }
1378  } // storeLabels()
1379

1380  // ----------------------------------------------------------
1381

1382  /**
1383   * <p>Copy a directory and index all its files as products inside this Category</p>
1384   * @param oConn JDCConnection Any pending transaction on given connection will be commited.
1385   * This methods calls Connection.commit() on oConn object,
1386   * so AutoCommit status for connection must be set to true before calling uploadDirectory()
1387   * @param sSourcePath String "file:///tmp/upload/myfiles"
1388   * @param sProtocol String "file://"
1389   * @param sServer String Server name (for FTP transfers)
1390   * @param sTargetPath String "file:///opt/hipergate/storege/domians/2050/..."
1391   * @param sLanguage String
1392   * @throws Exception
1393   * @throws IOException
1394   * @throws SQLException
1395   */

1396  public void uploadDirectory (JDCConnection oConn, String JavaDoc sSourcePath, String JavaDoc sProtocol,
1397                               String JavaDoc sServer, String JavaDoc sTargetPath, String JavaDoc sLanguage)
1398    throws Exception JavaDoc, IOException JavaDoc, SQLException JavaDoc {
1399    File JavaDoc oDir, oFile;
1400    File JavaDoc aFiles[];
1401    int iFiles;
1402    String JavaDoc sFileName, sBasePath, sTargetChomp, sNewCategoryId, sNewCategoryNm;
1403    Properties JavaDoc oURLProps;
1404    FileInputStream JavaDoc oIOStrm;
1405    PreparedStatement JavaDoc oStmt, oCatg;
1406    ResultSet JavaDoc oRSet;
1407
1408    Category oNewCategory;
1409    Product oProd;
1410    ProductLocation oLoca;
1411
1412    Object JavaDoc aCatValues[];
1413    Object JavaDoc aLblValues[];
1414    Short JavaDoc iTrue = new Short JavaDoc((short)1);
1415    Integer JavaDoc iActive = new Integer JavaDoc(1);
1416
1417    if (DebugFile.trace) {
1418      DebugFile.writeln("Begin Category.uploadDirectory([Connection], " + sSourcePath + ", ..., " + sTargetPath + "," + sLanguage + ")" );
1419      DebugFile.incIdent();
1420    }
1421
1422    if (null==oFS) {
1423      if (DebugFile.trace) DebugFile.writeln("new com.knowgate.dfs.FileSystem()");
1424      oFS = new FileSystem();
1425    }
1426
1427    // Crea la ruta base quitando el file:// de por delante
1428
sBasePath = sSourcePath.substring(sSourcePath.indexOf("://")+3);
1429
1430    if (DebugFile.trace) DebugFile.writeln("sBasePath=" + sBasePath);
1431
1432    oProd = new Product();
1433    oProd.put(DB.gu_owner, getString(DB.gu_owner));
1434
1435    // Obtiene un array con los archivos del directorio base
1436
oDir = new File JavaDoc(sBasePath);
1437    aFiles = oDir.listFiles();
1438    iFiles = aFiles.length;
1439
1440    if (DebugFile.trace) DebugFile.writeln(String.valueOf(iFiles) + " files found");
1441
1442    // Cursor preparado para leer los archivos de una categoría
1443
if (DebugFile.trace) DebugFile.writeln("Connection.prepareStatement(SELECT NULL FROM " + DB.k_products + " p, " + DB.k_x_cat_objs + " o WHERE p." + DB.nm_product + "=? AND o." + DB.gu_category + "=? AND o." + DB.id_class + "=" + String.valueOf(Product.ClassId) + " AND p." + DB.gu_product + "=o." + DB.gu_object);
1444    oStmt = oConn.prepareStatement("SELECT " + DB.gu_product + " FROM " + DB.k_products + " p, " + DB.k_x_cat_objs + " o WHERE p." + DB.nm_product + "=? AND o." + DB.gu_category + "=? AND o." + DB.id_class + "=" + String.valueOf(Product.ClassId) + " AND p." + DB.gu_product + "=o." + DB.gu_object, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
1445
1446    // Cursor preparado para buscar una categoría hija por nombre traducido
1447
if (DebugFile.trace) DebugFile.writeln("Connection.prepareStatement(SELECT " + DB.gu_category + " FROM " + DB.k_cat_tree + " t," + DB.k_cat_labels + " l WHERE t.gu_parent_cat=? AND l.tr_category=? AND t.gu_child_cat=l.gu_category");
1448    oCatg = oConn.prepareStatement("SELECT " + DB.gu_category + " FROM " + DB.k_cat_tree + " t," + DB.k_cat_labels + " l WHERE t." + DB.gu_parent_cat + "=? AND l." + DB.tr_category + "=? AND t." + DB.gu_child_cat + "=l." + DB.gu_category, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
1449
1450    for (int f=0; f<iFiles; f++) {
1451      oFile = aFiles[f];
1452      if (oFile.isFile()) {
1453        sFileName = oFile.getName();
1454
1455        if (DebugFile.trace) DebugFile.writeln("nm_product=" + (sFileName.length()<=128 ? sFileName : sFileName.substring(0,128)));
1456
1457        if (sFileName.toLowerCase().endsWith(".url"))
1458          // Si el archivo tiene extensión .url interpretarlo como un enlace
1459
oProd.put(DB.nm_product, (sFileName.length()<=128 ? sFileName.substring(0,sFileName.length()-4) : sFileName.substring(0,128)));
1460        else
1461          // Es un archivo físico
1462
oProd.put(DB.nm_product, (sFileName.length()<=128 ? sFileName : sFileName.substring(0,128)));
1463
1464        // Guardar el archivo como un producto en la base de datos
1465
oStmt.setString(1, oProd.getString(DB.nm_product));
1466        oStmt.setString(2, getString(DB.gu_category));
1467        oRSet = oStmt.executeQuery();
1468        if (oRSet.next())
1469          oProd.put(DB.gu_product, oRSet.getString(1));
1470        oRSet.close();
1471
1472        if (DebugFile.trace) DebugFile.writeln("oProd.store([Connection]);");
1473        oProd.store(oConn);
1474
1475        // Añadir el producto a la categoría actual
1476
if (DebugFile.trace) DebugFile.writeln("oProd.addToCategory([Connection], " + getStringNull(DB.gu_category, "null") + ");");
1477        oProd.addToCategory(oConn, this.getString(DB.gu_category), 0);
1478
1479        // Crear una nueva ubicación de producto para apuntar al archivo físico o al enlace
1480
oLoca = new ProductLocation();
1481
1482        oLoca.put(DB.gu_owner, getString(DB.gu_owner));
1483        oLoca.put(DB.gu_product, oProd.get(DB.gu_product));
1484
1485        if (sFileName.toLowerCase().endsWith(".url")) {
1486          // Si se trata de un archivo .url
1487
// abrirlo como un fichero de propiedades
1488
// para sacar los parámetros del enlace.
1489
oURLProps = new Properties JavaDoc();
1490          oIOStrm = new FileInputStream JavaDoc(oFile);
1491          oURLProps.load(oIOStrm);
1492          oIOStrm.close();
1493
1494          if (DebugFile.trace) DebugFile.writeln("URL=" + oURLProps.getProperty("URL", "null"));
1495
1496          oLoca.setURL(oURLProps.getProperty("URL"));
1497          oLoca.remove(DB.xfile);
1498          oLoca.remove(DB.xoriginalfile);
1499
1500          oLoca.put(DB.id_cont_type, oLoca.getContainerType());
1501          oLoca.setLength(0);
1502          if (DebugFile.trace) DebugFile.writeln("oLoca.store([Connection])");
1503          oLoca.store(oConn);
1504
1505          try { oConn.commit(); } catch (SQLException JavaDoc ignore) { /* Ignore exception if AutoCOmmit was already set to true*/}
1506        }
1507        else {
1508          // Si es una archivo físico moverlo de ubicación y apuntar su ruta en la base de datos
1509
oLoca.setPath (sProtocol, sServer, sTargetPath, sFileName, sFileName);
1510          oLoca.put(DB.id_cont_type, oLoca.getContainerType());
1511          oLoca.setLength(new Long JavaDoc(oFile.length()).intValue());
1512
1513          if (DebugFile.trace) DebugFile.writeln("oLoca.store([Connection])");
1514          oLoca.store(oConn);
1515
1516          try { oConn.commit(); } catch (SQLException JavaDoc ignore) { /* Ignore exception if AutoCOmmit was already set to true*/}
1517
1518          // Coger el fichero "sSourcePath/sFileName" y moverlo a "sProtocol://sServer/sTargetPath/sFileName"
1519
// luego grabar en la base de datos su nueva ubicación física
1520
oLoca.upload(oConn, oFS, sSourcePath, sFileName, sProtocol + sServer + sTargetPath, sFileName);
1521        }
1522        oLoca = null;
1523
1524        oProd.remove(DB.gu_product);
1525        oProd.remove(DB.nm_product);
1526      }
1527      else if (oFile.isDirectory()) {
1528        sFileName = oFile.getName();
1529
1530        if (sProtocol.startsWith("file://"))
1531          sTargetChomp = (sTargetPath.endsWith(System.getProperty("file.separator")) ? sTargetPath : sTargetPath + System.getProperty("file.separator"));
1532        else
1533          sTargetChomp = (sTargetPath.endsWith("/") ? sTargetPath : sTargetPath + "/");
1534
1535        oCatg.setString(1, getString(DB.gu_category));
1536        oCatg.setString(2, sFileName);
1537        oRSet = oCatg.executeQuery();
1538        if (oRSet.next()) {
1539          sNewCategoryId = oRSet.getString(1);
1540          oNewCategory = new Category(oConn, sNewCategoryId);
1541          sNewCategoryNm = oNewCategory.getString(DB.nm_category);
1542
1543          // Crear el directorio espejo donde se almacenan los archivos (Productos) de la categoría
1544
oFS.mkdirs(sProtocol + sServer + sTargetChomp + sNewCategoryNm);
1545        }
1546        else {
1547
1548          // Componer un nuevo alias (nombre corto único) para la categoria que representa el directorio
1549
sNewCategoryNm = Category.makeName(oConn, sFileName);
1550
1551          if (DebugFile.trace) DebugFile.writeln("sNewCategoryNm=" + sNewCategoryNm);
1552
1553          // Crear la categoría
1554
aCatValues = new Object JavaDoc[] { getString(DB.gu_category), getString(DB.gu_owner), sNewCategoryNm, iTrue, iActive, "folderclosed_16x16.gif", "folderopen_16x16.gif"};
1555          sNewCategoryId = Category.create(oConn, aCatValues);
1556
1557          // Crear la etiqueta de nombre traducido para la categoría
1558
aLblValues = new Object JavaDoc[] { sNewCategoryId, sLanguage, sFileName, null };
1559          CategoryLabel.create(oConn, aLblValues);
1560
1561          try { oConn.commit(); } catch (SQLException JavaDoc ignore) { /* Ignore exception if AutoCOmmit was already set to true*/}
1562
1563          // Crear el directorio espejo donde se almacenan los archivos (Productos) de la categoría
1564
oFS.mkdirs(sProtocol + sServer + sTargetChomp + sNewCategoryNm);
1565
1566          // Añadir archivos recursivamente
1567
oNewCategory = new Category(oConn, sNewCategoryId);
1568          oNewCategory.inheritPermissions(oConn, getString(DB.gu_category), (short)1, (short)1);
1569        }
1570        oRSet.close();
1571
1572        oNewCategory.uploadDirectory(oConn, "file://" + oFile.getAbsolutePath(), sProtocol, sServer, sTargetChomp + sNewCategoryNm, sLanguage);
1573      }
1574    }
1575
1576    if (DebugFile.trace) {
1577      DebugFile.decIdent();
1578      DebugFile.writeln("End Category.uploadDirectory()");
1579      }
1580
1581  } // uploadDirectory()
1582

1583  // **********************************************************
1584
// Static Methods
1585

1586  /**
1587   * <p>Create or Store Category.</p>
1588   * @param oConn Database Connection
1589   * @param sCategoryId GUID of Category to store or <b>null</b> if it is a new Category.
1590   * @param sParentId GUID of Parent Category or <b>null</b> if it is a root category.
1591   * @param sCategoryName Internal Category Name. It is recommended that makeName()
1592   * method is applied always on sCategoryName. Because category names are often used for composing
1593   * physical disk paths, assigning characters such as '*', '/', '?' etc. to category names may
1594   * lead to errors when creating directories for contained Products. As a general rule use ONLY
1595   * upper case letters and numbers for category names.
1596   * @param iIsActive 1 if category is to be marked active, 0 if it is to be marked as unactive.
1597   * @param iDocStatus Initial Document Status, { 0=Pending, 1=Active, 2=Locked } See k_lu_status table.
1598   * @param sOwner GUID of User owner of this Category.
1599   * @param sIcon1 Icon for closed folder.
1600   * @param sIcon2 Icon for opened folder.
1601   * @return GUID of new Category or sCategoryId if Category already existed.
1602   * @throws SQLException
1603   */

1604  public static String JavaDoc store(JDCConnection oConn, String JavaDoc sCategoryId, String JavaDoc sParentId, String JavaDoc sCategoryName, short iIsActive, int iDocStatus, String JavaDoc sOwner, String JavaDoc sIcon1, String JavaDoc sIcon2 ) throws SQLException JavaDoc {
1605    Category oCatg = new Category ();
1606    boolean isParentOfParent = false;
1607    Object JavaDoc aCatg[] = { null };
1608    DBSubset oNames;
1609
1610    if (DebugFile.trace) {
1611      DebugFile.writeln("Begin Category.store([Connection], " + sCategoryId + ", " + sParentId + ", sCategoryName" + ", ...)" );
1612      DebugFile.incIdent();
1613      }
1614
1615    oCatg.put (DB.gu_owner, sOwner);
1616    oCatg.put (DB.nm_category, sCategoryName);
1617    oCatg.put (DB.bo_active, iIsActive);
1618    oCatg.put (DB.id_doc_status, iDocStatus);
1619
1620    if (null!=sIcon1) oCatg.put (DB.nm_icon, sIcon1);
1621    if (null!=sIcon2) oCatg.put (DB.nm_icon2, sIcon2);
1622
1623      if (null!=sCategoryId) {
1624        oCatg.put (DB.gu_category, sCategoryId);
1625
1626        // Verificar que la categoria no es padre de si misma
1627
if (null!=sParentId) {
1628          if (sCategoryId.equalsIgnoreCase(sParentId)) {
1629            if (DebugFile.trace) DebugFile.writeln("ERROR: Category " + sCategoryName + " is its own parent");
1630            throw new SQLException JavaDoc("Category tree circular reference");
1631          } // endif (sCategoryId==sParentId)
1632

1633          // Si la categoria tiene padre (no es raiz) entonces
1634
// verificar que el padre no es a su vez un hijo de
1635
// la categoria para evitar la creacion de bucles.
1636
isParentOfParent = oCatg.isParentOf(oConn, sParentId);
1637        } // endif (sParentId)
1638

1639      } // endif (null!=sCategoryId)
1640

1641      if (isParentOfParent) {
1642        if (DebugFile.trace) DebugFile.writeln("ERROR: Category " + sCategoryName + " has a circular parentship relationship");
1643        throw new SQLException JavaDoc("Category tree circular reference");
1644      }
1645
1646      // Si la categoria ya existia, entonces
1647
// borrar todos los nombres traducidos (etiquetas)
1648
if (null!=sCategoryId) {
1649        if (DebugFile.trace) DebugFile.writeln("Clearing labels...");
1650        aCatg[0] = oCatg.getString(DB.gu_category);
1651        oNames = new DBSubset (DB.k_cat_labels, DB.id_language+","+DB.tr_category+","+DB.url_category, DB.gu_category+"=?",1);
1652        oNames.clear (oConn, aCatg);
1653        if (DebugFile.trace) DebugFile.writeln("Labels cleared.");
1654      }
1655      else
1656        oCatg.remove(DB.gu_category);
1657
1658      // Grabar la categoria,
1659
// si el campo id_category no existe (nueva categoria)
1660
// el metodo store lo rellenara automaticamente al grabar
1661
oCatg.store(oConn);
1662
1663      // Establecer si la categoria es raiz
1664
if (null==sParentId)
1665        oCatg.setIsRoot(oConn, true);
1666      else
1667        oCatg.setParent(oConn, sParentId);
1668
1669    if (DebugFile.trace) {
1670      DebugFile.decIdent();
1671      DebugFile.writeln("End Category.store() : " + oCatg.getString(DB.gu_category));
1672    }
1673
1674    // Recuperar el identificador unico de la categoria recien escrita
1675
return oCatg.getString(DB.gu_category);
1676  } // storeCategory()
1677

1678  // ----------------------------------------------------------
1679

1680  /**
1681   * <p>Delete Category and all its childs.</p>
1682   * First delete all Products and Companies contained in Category, including
1683   * physical disk files associted with Products and Company attachments.<br>
1684   * Then call k_sp_del_category_r stored procedure and perform recursive
1685   * deletion of all childs.
1686   * @param oConn Database Connection
1687   * @param sCategoryGUID GUID of Category to delete.
1688   * @throws SQLException
1689   */

1690  public static boolean delete(JDCConnection oConn, String JavaDoc sCategoryGUID)
1691    throws SQLException JavaDoc, IOException JavaDoc {
1692
1693    if (DebugFile.trace) {
1694       DebugFile.writeln("Begin Category.delete([Connection], " + sCategoryGUID + ")");
1695       DebugFile.incIdent();
1696     }
1697
1698     Category oCat = new Category(sCategoryGUID);
1699
1700     // Delete any child category first
1701
// New for v2.1
1702
DBSubset oChlds = oCat.getChilds(oConn);
1703     int iChilds = oChlds.getRowCount();
1704     for (int c=0; c<iChilds; c++)
1705       Category.delete(oConn, oChlds.getString(0,c));
1706
1707     Statement JavaDoc oStmt;
1708     Product oProd;
1709     DBSubset oObjs = oCat.getObjects(oConn);
1710     int iObjs = oObjs.getRowCount();
1711     boolean bRetVal;
1712
1713    // recorre los objetos de esta categoría y los borra
1714
for (int o=0; o<iObjs; o++) {
1715      switch (oObjs.getInt(1, o)) {
1716        case com.knowgate.hipergate.Product.ClassId:
1717          oProd = new Product(oConn, oObjs.getString(0, o));
1718          oProd.delete(oConn);
1719          break;
1720        case com.knowgate.crm.Company.ClassId:
1721          com.knowgate.crm.Company.delete(oConn, oObjs.getString(0, o));
1722          break;
1723        case com.knowgate.forums.NewsGroup.ClassId:
1724          com.knowgate.forums.NewsGroup.delete(oConn, oObjs.getString(0, o));
1725          break;
1726        case com.knowgate.hipergate.Image.ClassId:
1727          Image oImg = new com.knowgate.hipergate.Image(oConn, oObjs.getString(0, o));
1728          oImg.delete(oConn);
1729          break;
1730        case com.knowgate.hipermail.DBMimeMessage.ClassId:
1731          com.knowgate.hipermail.DBMimeMessage.delete(oConn, sCategoryGUID, oObjs.getString(0, o));
1732          break;
1733      }
1734    } // next (o)
1735

1736    oObjs = null;
1737
1738    if (DBBind.exists(oConn, DB.k_mime_msgs, "U")) {
1739      oObjs = new DBSubset(DB.k_mime_msgs, DB.gu_mimemsg, DB.gu_category + "='" + sCategoryGUID + "'", 1000);
1740      iObjs = oObjs.load(oConn);
1741
1742      if (oConn.getDataBaseProduct()==JDCConnection.DBMS_POSTGRESQL) {
1743        PreparedStatement JavaDoc oDlte = oConn.prepareStatement("SELECT k_sp_del_mime_msg(?)");
1744        ResultSet JavaDoc oRSet;
1745        for (int m=0; m<iObjs; m++) {
1746          oDlte.setString(1, oObjs.getString(0,m));
1747          oRSet = oDlte.executeQuery();
1748          oRSet.close();
1749        }
1750        oDlte.close();
1751      }
1752      else {
1753        CallableStatement JavaDoc oCall = oConn.prepareCall("{ call k_sp_del_mime_msg(?) }");
1754        for (int m=0; m<iObjs; m++) {
1755          oCall.setString(1, oObjs.getString(0,m));
1756          oCall.execute();
1757        }
1758        oCall.close();
1759      }
1760    } // fi (exists(k_mime_msgs))
1761

1762    oObjs = null;
1763
1764    if (DBBind.exists(oConn, DB.k_x_company_prods, "U")) {
1765
1766      oStmt = oConn.createStatement();
1767
1768      if (DebugFile.trace)
1769        DebugFile.writeln("Statement.executeUpdate(DELETE FROM " + DB.k_x_company_prods + " WHERE " + DB.gu_category + "='" + sCategoryGUID + "')");
1770
1771      oStmt.executeUpdate("DELETE FROM " + DB.k_x_company_prods + " WHERE " + DB.gu_category + "='" + sCategoryGUID + "'");
1772
1773      oStmt.close();
1774    } // fi (k_x_company_prods)
1775

1776    if (DBBind.exists(oConn, DB.k_x_contact_prods, "U")) {
1777
1778      oStmt = oConn.createStatement();
1779
1780      if (DebugFile.trace)
1781        DebugFile.writeln("Statement.executeUpdate(DELETE FROM " + DB.k_x_contact_prods + " WHERE " + DB.gu_category + "='" + sCategoryGUID + "')");
1782
1783      oStmt.executeUpdate("DELETE FROM " + DB.k_x_contact_prods + " WHERE " + DB.gu_category + "='" + sCategoryGUID + "'");
1784
1785      oStmt.close();
1786    } // fi (k_x_contact_prods)
1787

1788    // Saca la lista de categorías hijas de primer nivel y repite el proceso de borrado
1789
LinkedList JavaDoc oChilds = oCat.browse(oConn, BROWSE_DOWN, BROWSE_BOTTOMUP);
1790    ListIterator JavaDoc oIter = oChilds.listIterator();
1791
1792    while (oIter.hasNext()) {
1793      oCat = (Category) oIter.next();
1794      oCat.delete(oConn);
1795    } // wend
1796

1797    if (oConn.getDataBaseProduct()==JDCConnection.DBMS_POSTGRESQL) {
1798      if (DebugFile.trace) DebugFile.writeln("Connection.executeQuery(SELECT k_sp_del_category_r ('" + sCategoryGUID + "'))");
1799      oStmt = oConn.createStatement();
1800      oStmt.executeQuery("SELECT k_sp_del_category_r ('" + sCategoryGUID + "')");
1801      oStmt.close();
1802      bRetVal = true;
1803    } else {
1804      if (DebugFile.trace) DebugFile.writeln("Connection.prepareCall({call k_sp_del_category_r('" + sCategoryGUID + "')})");
1805      CallableStatement JavaDoc oCall = oConn.prepareCall("{call k_sp_del_category_r ('" + sCategoryGUID + "')}");
1806      bRetVal = oCall.execute();
1807      oCall.close();
1808    }
1809
1810    if (DebugFile.trace) {
1811      DebugFile.decIdent();
1812      DebugFile.writeln("End Category.delete() : " + String.valueOf(bRetVal));
1813    }
1814    return bRetVal;
1815  } // delete
1816

1817  // ----------------------------------------------------------
1818

1819  /**
1820   * Create new Category with translated labels.
1821   * @param oConn Database Connection
1822   * @param Values An array with the following elements:<br>
1823   * { (String) gu_parent, (String) gu_owner, (String) nm_category,
1824   * (Short) bo_active, (Short) id_doc_status, (String) nm_icon, (String) nm_icon2 }
1825   * @return GUID of new Category
1826   * @throws SQLException
1827   */

1828  public static String JavaDoc create(JDCConnection oConn, Object JavaDoc[] Values) throws SQLException JavaDoc {
1829    Category oCatg = new Category ();
1830
1831    oCatg.put (DB.gu_owner, Values[1]);
1832    oCatg.put (DB.nm_category, Values[2]);
1833    oCatg.put (DB.bo_active, Values[3]);
1834    oCatg.put (DB.id_doc_status, Values[4]);
1835    oCatg.put (DB.nm_icon, Values[5]);
1836    if (Values[6]!=null)
1837      oCatg.put (DB.nm_icon2, Values[6]);
1838    else
1839      oCatg.put (DB.nm_icon2, Values[5]);
1840
1841    // Grabar la categoria, el metodo store
1842
// rellenara automaticamente el campo gu_category
1843
oCatg.store(oConn);
1844
1845    // Establecer el padre
1846
if (null!=Values[0])
1847      oCatg.setParent(oConn, Values[0].toString());
1848    else
1849      oCatg.setIsRoot(oConn, true);
1850
1851    // Recuperar el identificador unico de la categoria recien escrita
1852
return oCatg.getString(DB.gu_category);
1853  } // create()
1854

1855  // ----------------------------------------------------------
1856

1857  /**
1858   * <p>Get Category GUID given its internal name.</p>
1859   * Category name is column nm_category at table k_categories.<br>
1860   * This Java method calls k_sp_get_cat_id database stored procedure.
1861   * @param oConn Database Connection
1862   * @param sCategoryNm Category Internal Name
1863   * @return Category GUID or <b>null</b> if no Category with such name is found.
1864   * @throws SQLException
1865   */

1866  public static String JavaDoc getIdFromName(JDCConnection oConn, String JavaDoc sCategoryNm) throws SQLException JavaDoc {
1867    if (DebugFile.trace) {
1868     DebugFile.writeln("Begin Category.getIdFromName([Connection], " + sCategoryNm + ")" );
1869     DebugFile.incIdent();
1870     }
1871
1872    String JavaDoc sCatId = DBPersist.getUIdFromName(oConn, null, sCategoryNm, "k_sp_get_cat_id");
1873
1874    if (DebugFile.trace) {
1875      DebugFile.decIdent();
1876      DebugFile.writeln("End Category.getIdFromName() : " + sCatId);
1877    }
1878
1879    return sCatId;
1880  } // getIdFromName()
1881

1882  // ----------------------------------------------------------
1883

1884  /**
1885   * <p>Make an internal category name from an arbitrary string.</p>
1886   * Because nm_category is a primary key for table k_categories and because
1887   * category names are used for composing physical disk paths, some special
1888   * rules must be followed when assigning category names.<br>
1889   * <ul>
1890   * <li><b>First</b> a Category Name MUST NOT containing any character not allowed in a directory name.
1891   * <li><b>Second</b> a Category Name MUST be unique for all categories at all WorkAreas.
1892   * </ul>
1893   * @param oConn Database Connection
1894   * @param sCategoryNm String to be used as a guide for making category name.
1895   * @return The input string truncated to 18 characters and transformed to upper case.
1896   * Method Gadgets.ASCIIEncode() is applies and spaces, commas, asterisks, slashes,
1897   * backslashes and other characters are removed or substituted.
1898   * Finally an 8 decimals integer tag is appended to name for making it unique.
1899   * For example "Barnes & Noble" is transormed to "BARNES_A_NOBLE~00000001"
1900   * @throws SQLException
1901   */

1902  public static synchronized String JavaDoc makeName(JDCConnection oConn, String JavaDoc sCategoryNm) throws SQLException JavaDoc {
1903    String JavaDoc sCatNm;
1904    int iChurriguito;
1905    String JavaDoc sCatIndex;
1906
1907    if (DebugFile.trace) {
1908      DebugFile.writeln("Begin Category.makeName([Connection], " + sCategoryNm + ")" );
1909      DebugFile.incIdent();
1910      }
1911
1912    String JavaDoc sShortCategoryNm = (sCategoryNm.length()>18 ? sCategoryNm.substring(0, 18) : sCategoryNm);
1913    sShortCategoryNm = Gadgets.ASCIIEncode(sShortCategoryNm);
1914    sShortCategoryNm.replace(' ', '_');
1915    sShortCategoryNm.replace(',', '_');
1916    sShortCategoryNm.replace(';', '_');
1917    sShortCategoryNm.replace('"', 'q');
1918    sShortCategoryNm.replace('|', '_');
1919
1920    // Obtener el máximo de las categorías cuyo alias es igual al buscado
1921
if (DebugFile.trace) DebugFile.writeln("Connection.prepareStatement(SELECT " + DBBind.Functions.ISNULL + "(MAX(" + DB.nm_category + "),'" + sShortCategoryNm + "~00000000') FROM " + DB.k_categories + " WHERE " + DB.nm_category + " LIKE '" + sShortCategoryNm + "%')");
1922
1923    PreparedStatement JavaDoc oStmt = oConn.prepareStatement("SELECT " + DBBind.Functions.ISNULL + "(MAX(" + DB.nm_category + "),'" + sShortCategoryNm + "~00000000') FROM " + DB.k_categories + " WHERE " + DB.nm_category + " LIKE ?", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
1924
1925    oStmt.setString(1, sShortCategoryNm + "%");
1926    ResultSet JavaDoc oRSet = oStmt.executeQuery();
1927    if (oRSet.next()) {
1928      sCatNm = oRSet.getString(1);
1929    }
1930    else
1931      sCatNm = sShortCategoryNm + "~00000000";
1932    oRSet.close();
1933    oStmt.close();
1934
1935    // Buscar el churriguito y sacar los números que quedan a la derecha
1936
iChurriguito = sCatNm.indexOf("~");
1937    if (iChurriguito>0)
1938      sCatIndex = String.valueOf(Integer.parseInt(sCatNm.substring(iChurriguito+1)) + 1);
1939    else
1940      sCatIndex = "00000001";
1941
1942    // Añadir zeros de padding por la izquierda
1943
for (int z=0; z<8-sCatIndex.length(); z++) sCatIndex = "0" + sCatIndex;
1944
1945    sShortCategoryNm += "~" + sCatIndex;
1946
1947    if (DebugFile.trace) {
1948      DebugFile.decIdent();
1949      DebugFile.writeln("End Category.makeName() : " + sShortCategoryNm);
1950    }
1951
1952    return sShortCategoryNm;
1953  } // makeName
1954

1955  // **********************************************************
1956
// Constantes Publicas
1957

1958  public static final int BROWSE_UP = 0;
1959  public static final int BROWSE_DOWN = 1;
1960
1961  public static final int BROWSE_TOPDOWN = 0;
1962  public static final int BROWSE_BOTTOMUP = 1;
1963
1964  public static final short ClassId = 10;
1965
1966  // **********************************************************
1967
// Variables Privadas
1968

1969  private DBSubset oParents;
1970  private DBSubset oChilds;
1971  private DBSubset oNames;
1972  private DBSubset oACLGroups;
1973  private DBSubset oACLUsers;
1974  private FileSystem oFS;
1975}
1976
Popular Tags