001    /***************************************************************************************************
002     *               MODULE DESCRIPTION
003     ****************************************************************************************************
004     *
005     *               NAME:           KiuruSpace.java
006     *               LANGUAGE:       Java2
007     *               DATE:           19.11.2002
008     *               AUTHOR:         Miika Nurminen, University of Jyväskylä
009     *
010     ****************************************************************************************************
011     *               COPYRIGHT (C) KIURU -PROJECT GROUP
012     *               Limited rights granted. Please refer to license
013     ****************************************************************************************************
014     *  
015     ****************************************************************************************************
016     *               UPDATES
017     ****************************************************************************************************
018     *
019     *   19.11.2002: Initial release / mn
020     *   25.4.2003: Enum test
021     *   
022     ****************************************************************************************************/
023    
024    package kiurubeans;
025    
026    import java.beans.*;
027    import kotkabeans.*;
028    import kolibribeans.*;
029    import java.lang.*;
030    import java.util.*;
031    import java.sql.*;
032    import javax.servlet.http.HttpServletRequest;
033    
034    /**
035     * Representation of Space db entity.
036     *
037     * @author Miika Nurminen
038     */
039    public class KiuruSpace extends EntityHandler {
040    
041    // Attributes 
042      
043      /** Selects spacegroups for this space*/
044      public static final int ADD_SPACEGROUP=5;
045      
046      /** Confirms adding spacegroups to this space*/
047      public static final int ADD_SPACEGROUP_CONFIRM=6;
048    
049      /**
050       * List of available reservation mehtods.
051       * @deprecated timmi-material.
052       * This should be LinkedHashMap (not implemented in java 1.3.1
053       */
054      private ArrayList reservationMethodList;
055      
056      /**
057       * Space's name (or code)
058       */
059      private String name = "";
060      
061      /**
062       * Space's size. Internally one of space's resources.
063       */
064      private int size = 20;
065      
066      /** 
067       * Indicates is space is reserved by korppi and/or timmi (or any)
068       * @deprecated timmi-material
069       * reservationMethod should probably be deprecated. it's here for
070       * background compatibility.
071       */
072      private String reservationMethod = "";
073      
074      /**
075       * Space's id. -1 indicates a new space.
076       */
077      private int spaceId = -1;
078      
079      /**
080       * Space's organisation id. ''Official space'' is defined by space
081       * that has organisationid<>NULL and <>0.
082       * required when updating space's responsible organisation
083       */
084      private int organisationId = 0; 
085      
086      /**
087       * Space's type. Space types are defined as follows:
088       * <p>
089       *  0 -  -- <br>
090       *  1 - Opetustila<br>
091       *  2 - Mikroluokka<br>
092       *  3 -  Kokoustila<br>
093       *  4 - Työhuone<br>
094       *  5 - Yleistila<br>
095       *  6 - Oheisvarattava<br>
096       *  7 -  Muu tila
097       * <p>
098       * These should be put in a separate enum structure.
099       */
100      private int spaceType = 0;  // 7 == muu tila
101      
102      /**
103       * User's selected space groups to be joined to this space.
104       */
105      private String[] selectedSpaceGroups = new String[0];
106                       
107    
108    // Constructors
109     
110      /** Constructor for KiuruSpace. Does not read anything from db.
111       * @param id The spaceId for the space
112       * @param e Error objects. Possible error messages are delivered here.
113       */  
114      public KiuruSpace(int id,kotkabeans.Error e) {
115        setSpaceId(id);
116        setError(e);
117      }
118      
119      /** Default constructor */  
120      public KiuruSpace() {
121        reservationMethodList = new ArrayList();
122        reservationMethodList.add(new StringPair("Korppi","Varaus vain Korpin kautta"));
123        reservationMethodList.add(new StringPair("Timmi","Varaus Korpin ja Timmin kautta"));
124        reservationMethodList.add(new StringPair("Ei","Ei varauksia"));
125      }
126      
127    // Access methods
128    
129      /** 
130       * Returns current max state value. Inherited classes may override this
131       * when new states are introduced.
132       *
133       * @return max state value
134       */
135      protected int getMaxState() {
136        return 6;
137      }
138    
139      /** Returns if entity is in a state of adding a new record.
140       * Implementation depends of a descendant class.
141       * @return true, if the space is in a state of adding a new record.
142       */
143      public boolean getAddingNew() {
144        return (getSpaceId()==-1);
145      }
146    
147      /** Returns the list of available reservation methods for spaces. The list contains
148       * methods written in Finnish.
149       * @return Arraylist that contains available reservation methods for spaces.
150       */  
151      public ArrayList getReservationMethodList() {
152        return this.reservationMethodList;
153      }
154    
155      /** Returns the of the space
156       * @return The name of the space.
157       */  
158      public String getName() {
159        return this.name;
160      }
161      
162      /** Sets the name of the space
163       * @param name Name of the space
164       */  
165      public void setName(String name) {
166        String s = KiuruString.sqlTrim(name);
167        if (s.length()==0) {
168          setOk(false);
169          addError("Nimi ei voi olla tyhjä!");
170          return;
171        }
172        this.name = s;
173      }
174      
175      /** Returns the size of the space as int number.
176       * @return The size of the space as int.
177       */  
178      public int getIntSize() {
179        return this.size;
180      }
181      
182      // even if internally int, property must have string getters & setters
183      /** Returns the size of the space in String. String contains integer number.
184       * @return String that contains the size of the space. Size is integer number.
185       */  
186      public String getSize() {
187        return Integer.toString(this.size);
188      }
189      
190      /** Sets the size of the space.
191       * @param size How many people are allowed to be in the space at the same time.
192       */  
193      public void setSize(int size) {
194        this.size = size;
195      }
196      
197      /** Sets the size of the space. String must contain a non-negative integer
198       * number.
199       * @param size String that tells how many people are allowed to be in the space at the same
200       * time. String has to contain a non-negative integer number.
201       */  
202      public void setSize(String size) {
203        try {
204          this.size=Integer.parseInt(size);
205        }
206        catch (Exception e) { /*this.size=-1;*/ setOk(false);
207          addError("Virheellinen paikkamäärä!");
208        }
209      }
210      
211      /** Returns the name of the reservation method used for this space.
212       * @return The reservation method used for this space
213       */  
214      public String getReservationMethod() {
215        return this.reservationMethod;
216      }
217      
218      /** Sets reservation method for this space.
219       * @param reservationMethod How is reservations supervised. Not really needed if we use only Korppi
220       */  
221      public void setReservationMethod(String reservationMethod) {
222        for (int i=0; i<reservationMethodList.size(); i++) {
223          if ( ( (StringPair)(reservationMethodList.get(i)) ).getKey().equals(reservationMethod) ) {
224            this.reservationMethod = reservationMethod;
225            return;
226          }
227        }
228        // reservationMethod was not found in the list => error
229        setOk(false);
230        addError("Virheellinen varaustapa!");
231      }
232      
233      /** Returns the spaceId of the current object.
234       * @return ID of space.
235       */  
236      public int getSpaceId() {
237        return this.spaceId;
238      }
239      
240      /** Sets the id for the current space. Use with caution, 
241       * this should be persistent for an objecct. -1 indicates a new record.
242       * @param id New spaceId
243       */  
244      public void setSpaceId(int id) {
245        this.spaceId=id;
246        // note: id -1 means new record!
247      }
248      
249      /** Sets the spaceId for the current space.
250       * @param id String containing the new space id. id must be an integer.
251       */  
252      public void setSpaceId(String id) {
253        try {
254          setSpaceId(Integer.parseInt(id));
255        }
256        catch (Exception e) {
257          setOk(false);
258          addError("Virheellinen salin ID-numero! ");
259        }
260      }
261      
262      /** Organisation that "owns" the space.
263       * @param i Id of the organisation
264       */  
265      public void setOrganisationId(int i) {
266        this.organisationId=i;
267      }
268      
269      /** Returns the organisation that "owns" this space.
270       * @return OrganisationId of the organisation
271       */  
272      public int getOrganisationId() {
273        return this.organisationId;
274      }
275    
276      /** Returns the type of space.
277       * @return SpaceTypeId of the space.
278       */  
279      public int getType() {return spaceType;}
280    
281      /** Sets the type of the space.
282       * @param spaceType spaceTypeId of the new type.
283       */  
284      public void setType(int spaceType) {this.spaceType=spaceType;}
285      
286    
287      /** Returns the selected spaceGroups.
288       * @return The spaceGroups the user has selected for this space.
289       */  
290      public String[] getSelectedSpaceGroups() { return selectedSpaceGroups; }
291      /** User wants to e.g. add this space into these spaceGroups
292       * @param s The string array containing the ids of the spaceGroups the user has selected.
293       */  
294      public void setSelectedSpaceGroups(String[] s) { selectedSpaceGroups=s; }
295      /** Sets the <i>i</i>th selected spacegroup
296       * @param i Which spaceGroup is going to be set
297       * @param s The id of the selected spaceGroup
298       */  
299      public void setSelectedSpaceGroups(int i,String s) { selectedSpaceGroups[i]=s; }
300      /** Returns the <i>i</i>th selected spaceGroup
301       * @return The id of the selected spaceGroup
302       * @param i Which spaceGroup is given
303       */  
304      public String getSelectedSpaceGroups(int i) { return selectedSpaceGroups[i]; }
305    
306      
307      /** Used with html forms. Changes bean state to AddNew.
308       * 'this' should be initialized!
309       * @param s We are not interested in the content of the string, 
310       * because it can be translated. The most important thing is that it exists.
311       * @see EntityHandler#RESET_RECORD
312       */
313      public void setSubmitAdd(String s) {
314        setEnumState(RESET_RECORD);
315      }
316      
317      /** Used with html forms. Changes bean state to searchWithId, so 'this' can
318       * be modified.
319       * id property should be set before call to performAction
320       * @param s We are not interested in the content of the string, 
321       * because it can be translated. The most important thing is that it exists.
322       * @see EntityHandler#GET_RECORD
323       */
324      public void setSubmitModify(String s) {
325        setEnumState(GET_RECORD);
326      }
327      
328      /** Used with html forms. Changes the internal state of the bean.
329       * @param s We are not interested in the content of the string, 
330       * because it can be translated. The most important thing is that it exists.
331       * @see EntityHandler#POST_RECORD
332       */  
333      public void setSubmitPost(String s) {
334        setEnumState(POST_RECORD);
335      }
336      
337      /** Used with html forms. Changes the internal state of the bean.
338       * @param s We are not interested in the content of the string, 
339       * because it can be translated. The most important thing is that it exists.
340       * @see EntityHandler#DELETE_RECORD
341       */  
342      public void setSubmitDeleteRecord(String s) {
343        setEnumState(DELETE_RECORD);
344      }
345    
346      
347      /** Used with html forms. Changes the internal state of the bean.
348       * @param s We are not interested in the content of the string, 
349       * because it can be translated. The most important thing is that it exists.
350       * @see #ADD_SPACEGROUP
351       */  
352      public void setSubmitAddSpaceGroup(String s) {
353        setEnumState(ADD_SPACEGROUP);
354      }
355      
356      /** Used with html forms. Changes the internal state of the bean.
357       * @param s We are not interested in this, because it can be translated. The most important
358       * thing is that it exists.
359       * @see #ADD_SPACEGROUP_CONFIRM
360       */  
361      public void setSubmitAddSpaceGroupConfirm(String s) {
362        setEnumState(ADD_SPACEGROUP_CONFIRM);
363      }
364      
365    
366    
367    // Operations
368      
369      /** Clears field values.
370       * <p>
371       * Result should be equivalent to constructing a new object.
372       * Nothing is saved to database.
373       */
374      public void resetRecord() {
375        setSelectedSpaceGroups(null);
376        this.name=""; // setting name would cause an exception
377        setSize(20);
378        setReservationMethod("Korppi");
379        setSpaceId(-1); // implicit addingnew
380        setType(0);
381      }
382      
383      
384      /** Performs action based on actionType (eg. addNew, modify, post, delete).
385       * Inherited classes may override this method to introduce custom actions.
386       * @throws Exception If something went wrong in the actual actions performed.
387       */
388      protected void defaultAction() throws java.lang.Exception {
389        switch (getEnumState()) {
390          case ADD_SPACEGROUP_CONFIRM:
391            addSpaceGroups();
392          break;
393          default:
394            super.defaultAction(); // post & others
395          break;
396        }
397      }
398      
399    
400    
401      /** Gets the data for the space from the database according to the spaceId.
402       * @throws Exception If database handling was not successful
403       */  
404      public void assignSpaceFromDataBase() throws Exception {
405        if (getAddingNew()) { // this might be generalized
406          throw new IllegalStateException("Cannot get a nonexistent record!");
407        }
408        assignSpaceFromDataBase(getSpaceId());
409      }
410    
411      
412      /** Gets the data for the KiuruSpace from database using existing connection.
413       * @param db Database connection
414       * @param aid spaceId of the wanted space.
415       * @throws Exception If something went wrong during the database query.
416       */  
417      public void assignSpaceFromDataBase(DB db, int aid) throws Exception {
418        RS2 rs;
419          setSelectedSpaceGroups(null);
420    
421          rs = new RS2(db.executeQuery("select deleted,code,spaceid,organisationid,spacetypeid from space where spaceid='"+aid+"' and deleted='false'"));
422          if (!SimpleDb.checkIfEditable(rs)) 
423            return;
424          setSpaceId(rs.getInt("spaceid"));
425          setName(rs.getString("code"));
426          setType(rs.getInt("spacetypeid"));
427          setOrganisationId(rs.getInt("organisationid"));
428          
429          // setting reservation method
430          rs.getInt("organisationid");
431          if (rs.wasNull())
432            setReservationMethod("Ei");
433          else {
434            rs = new RS2(db.executeQuery("select deleted, spaceid from spaceparameter "+
435            "where deleted=false and spaceid="+getSpaceId()+" "+
436            "and spaceparametertypeid=1"));
437                          // timmispaceid
438            if (rs.count()>0)
439              setReservationMethod("Timmi");
440            else
441              setReservationMethod("Korppi");
442          }
443          
444          // setting resources
445          rs = new RS2(db.executeQuery("select value from spaceresource "+
446          "where spaceid="+getSpaceId()+" and resourceid=1 and deleted='false'"));
447          // number_of_seats
448          if (rs.next()) {
449            try {
450              setSize(Integer.parseInt(rs.getString("value")));
451            }
452            catch (ClassCastException c) {
453              setSize(0);
454            }
455          }
456      }
457      
458      /** Gets the data for the kiuruSpace from database. Opens a new database connection.
459       * @param aid The spaceId of wanted space.
460       * @throws Exception If something went wrong during database handling.
461       */  
462      public void assignSpaceFromDataBase(int aid) throws Exception {
463        DB db=new DB("Space-beania");
464        db.connect();
465        try {
466          assignSpaceFromDataBase(db,aid);
467        }
468        finally {
469          db.disconnect();
470        }
471      }
472      
473      /** Creates a new kiuruSpace object and gets data from database for newly created
474       * kiuruSpace.
475       * @param aid spaceId of the wanted space.
476       * @throws Exception If something went wrong during database handling.
477       * @return KiuruSpace object.
478       */  
479      public static KiuruSpace getSpaceFromDataBase(int aid) throws Exception {
480        KiuruSpace result = new KiuruSpace();
481        result.assignSpaceFromDataBase(aid);
482        return result;
483      }
484      
485      /** Creates a new kiuruSpace object and gets data from database for newly created
486       * kiuruSpace. Uses existing database connection.
487       * @param db Database connection.
488       * @param aid spaceId of the wanted space.
489       * @throws Exception If something went wrong during database handling.
490       * @return KiuruSpace object.
491       */   
492      public static KiuruSpace getSpaceFromDataBase(DB db,int aid) throws Exception {
493        KiuruSpace result = new KiuruSpace();
494        result.assignSpaceFromDataBase(db,aid);
495        return result;
496      }
497      
498    
499      /** Tells if data in the object has changed compared with data stored in the database.
500       * @param db open db to be used.
501       * @throws Exception Database handling was not ok.
502       * @return True if the data of the object matches with the data stored in the database.
503       */  
504      private boolean dataChanged(DB db) throws Exception {
505        if (getAddingNew()) {
506          throw new IllegalStateException("Cannot check whether a new record is changed!");
507        }
508        if (equals(KiuruSpace.getSpaceFromDataBase(db,getSpaceId()))) {  // if objects are not equal, data is changed.
509          addError("Tietoja ei ole muutettu!");
510          return false; 
511        }
512        return true; 
513      }
514      
515      /** Stores the data of the object into the database
516       * @throws Exception Saving into the database was not ok.
517       */  
518      public void putSpaceToDataBase() throws Exception {
519        DB db=new DB("Updating space");
520        db.connect();
521        boolean addNew=false;
522        try {
523          if (getAddingNew()) { // create new
524            addNew=true;
525            BookTime b = new BookTime();
526            setSpaceId(b.insertPlace(getName()));
527          }
528          else { // update
529            if (!dataChanged(db)) {
530              db.disconnect();
531              return; // no changes, we can exit
532            }
533            
534            db.executeUpdate("update space set code='"+getName()+"' "+
535            "where deleted='false' and spaceid="+getSpaceId());
536          }
537          String org=null;
538          if (getOrganisationId()!=0) org=Integer.toString(getOrganisationId());
539          String typ=null;
540          if (getType()!=0) typ=Integer.toString(getType());
541          db.executeUpdate("update space set organisationid="+org+", spacetypeid="+typ+" where deleted=false and spaceid="+getSpaceId());
542    
543          // add TIMMI handling here!
544          if (getReservationMethod().equals("Ei")) {
545            db.executeUpdate("update space set organisationid=null"+
546            " where deleted='false' and spaceid='"+getSpaceId()+"'");
547          }
548          else {
549            db.executeUpdate("update space set organisationid='"+getOrganisationId()+
550            "' where deleted='false' and spaceid='"+getSpaceId()+"'");
551          }
552          
553          RS2 rs = new RS2(db.executeQuery("select spaceid,resourceid from spaceresource "+
554          "where spaceid="+getSpaceId()+" and resourceid=1 and deleted='false'"));
555          // #_of_seats
556          if (rs.next()) {
557            db.executeUpdate("update spaceresource set value='"+getSize()+"' "+
558            "where spaceid="+getSpaceId()+" and resourceid=1 and deleted='false'");
559            // #_of_seats
560          }
561          else {
562            db.executeUpdate("insert into spaceresource (deleted,spaceid,resourceid,value) "
563            +"values ('false',"+getSpaceId()+",1,'"+getSize()+"')");
564            // number of seats
565          }
566        }
567        finally {
568          db.disconnect();
569        }
570        if (addNew)
571          addNotice("Lisätty sali "+getName()+".");
572        else 
573          addNotice("Salin "+getName()+" tiedot päivitetty!");
574      }
575    
576      /**
577       *  Deletes current space & relations to resource, spacegroup & event. NOTE! There may be other relations to Space!
578       *  Deletion is NOT SAFE! It should be used with extreme caution.
579       *  Does NOT check if there are active events for a particular space!
580       */
581      public void deleteRecord() {
582        if (getUser()==null) {
583          throw new IllegalArgumentException("User must be assigned!");
584        }
585        if (!getUser().hasAdminRight()) {
586          addError("Sinulla ei ole oikeutta salin poistamiseen!");
587          return;
588        }
589        
590        StatementContainer[] sc = new StatementContainer[4];
591        sc[0]=new StatementContainer("update space set deleted=true where spaceid = ?");
592        sc[1]=new StatementContainer("update spacegroupspace set deleted=true where spaceid = ?");
593        sc[2]=new StatementContainer("update spaceresource set deleted=true where spaceid = ?");
594        sc[3]=new StatementContainer("update eventspace set deleted=true where spaceid = ?");
595        for (int i=0; i<4; i++)
596          sc[i].addStatement(new IntItem(getSpaceId()));
597        
598    
599        if (SimpleDb.executeTransaction(sc, "Space.deleteRecord db")) {
600          addNotice("Sali "+getName()+" poistettu!");
601        }
602        else {
603          addError("Virhe salia "+getName()+" poistettaessa. Mitään ei poistettu.");    
604        }
605        
606      }
607      
608    
609      /**
610       * Adds current space to selected space groups.
611       * 
612       * @throws Exception if there is a problem with db connection.
613       */  
614      public void addSpaceGroups() throws java.lang.Exception {
615        if (getSelectedSpaceGroups().length==0) {
616          addError("Liitettäviä saliryhmiä ei valittu!");    
617          return;
618        }
619        // this should be replaced with a single container with varying parameters!
620        StatementContainer[] sc = new StatementContainer[getSelectedSpaceGroups().length];
621        
622        String insertStr = "insert into spacegroupspace (deleted,spaceid,spacegroupid) values (false,"+getSpaceId()+",?)";
623        String updateStr = "update spacegroupspace set deleted=false where spaceid="+getSpaceId()+" and spacegroupid=?";
624        DB db = new DB("Space.addSpaceGroups prepare db");
625        try {
626          db.connect();
627          
628        // checking  if spacegroups exist
629        StringPair[] sp = new StringPair[2];
630        sp[0] = new StringPair("spaceid", Integer.toString(getSpaceId()));
631        sp[1] = new StringPair("spacegroupid");
632        for (int i=0; i<getSelectedSpaceGroups().length; i++) {
633          sp[1].setValue(getSelectedSpaceGroups(i));
634          if (SimpleDb.recordExists(db,"SpaceGroupSpace",sp))
635            sc[i]=new StatementContainer(updateStr);
636          else
637            sc[i]=new StatementContainer(insertStr);
638          
639          sc[i].addStatement(new IntItem((Integer.parseInt(getSelectedSpaceGroups(i)))));
640        }
641    
642        } finally {
643        db.disconnect();
644      }
645          
646        if (SimpleDb.executeTransaction(sc, "Space.addSpaceGroups db")) {
647          addNotice("Sali liitetty saliryhmiin!");
648        }
649        else {
650          addError("Virhe saliryhmiä liitettäessä. Mitään ei lisätty.");    
651        }
652        if (getSelectedSpaceGroups().length==0) {
653          addError("Liitettäviä saliryhmiä ei valittu!");    
654          return;
655        }  
656      }
657      
658      /** Returns all spacegrouptypes from database.
659       * @return RS2 containing <CODE>name</CODE> and <CODE>spacetypeid</CODE> of the
660       * spacegrouptypes.
661       * @throws Exception Database handling was not ok.
662       */
663      public static RS2 getSpaceTypes() throws Exception {
664        // note! the result should be customized according to user's access rights
665        return SimpleDb.simpleQuery("Getting SpaceTypes","select name,spacetypeid from spacetype where deleted='false' order by spacetypeid");
666      }
667      
668      /** Checks if given user has rights to make reservations to given space.
669       * @param spaceID spaceId of the space where user wants to make reservations.
670       * @param user User who is making the reservation.
671       * @throws Exception Database query was not ok.
672       * @return True if user is allowed to make reservations to given space.
673       */  
674      public static boolean checkUserRights(int spaceID,User user) throws Exception {
675        if (user==null) return false;
676        if (user.hasAdminRight()) return true;
677        boolean access=false;
678        DB db=new DB("checkUserRights");
679        try {
680          db.connect();
681          ResultSet rs = db.executeQuery(
682            "select space.spaceid from space,spacegroupspace,spacegroupperson "+
683            "where spacegroupspace.spaceid=space.spaceid "+
684            "and spacegroupspace.spacegroupid=spacegroup.spacegroupid "+
685            "and spacegroupperson.spacegroupid=spacegroup.spacegroupid "+
686            "and spacegroupperson.personid="+user.getPersonID()+
687            " and space.spaceid="+spaceID+" and spacegroup.spacegrouptypeid<5 "+
688            "and spacegroupperson.accesslevel>0 and space.deleted='false' "+
689            "and spacegroupspace.deleted='false' and spacegroupperson.deleted='false';");
690          if (rs.next()) {access=true;}
691        }
692        finally {
693          db.disconnect();
694        }
695        return access;  
696      }
697      
698      /** Checks if given user has rights to make reservation requests to given space.
699       * @return True if user is allowed to make reservation requests to given space.
700       * @param spaceId spaceId of the space where user wants to make reservations.
701       * @param user User who is making the reservation request.
702       * @throws Exception Database query was not ok.
703       */  
704      public static boolean checkReservationRequestRight(int spaceId, User user) throws java.lang.Exception {
705        if (user==null) return false;
706        if (user.hasAdminRight()) return true;
707        StringBuffer sb = new StringBuffer(200);
708        StringPair[] tables = {
709          new StringPair("s","space"),
710          new StringPair("sg","spacegroup"),
711          new StringPair("sgs","spacegroupspace")
712        };
713        sb.append("select distinct s.spaceid, sg.accessrightlevelid");
714        sb.append(SimpleDb.addSqlFrom(tables));
715        sb.append("where sgs.spaceid=s.spaceid ");
716        sb.append("and sgs.spacegroupid=sg.spacegroupid ");
717        sb.append(" and space.spaceid="+spaceId+" and spacegroup.spacegrouptypeid<5 ");
718        sb.append("and sg.accessrightlevelid<="+user.getAccessRightLevelID());
719        sb.append(SimpleDb.addSqlDeleted(tables));
720        RS2 rs = SimpleDb.simpleQuery("KiuruSpace.checkReservationRequestRight", sb.toString());
721        return (rs.next());
722      }
723    
724      /** Tells if current KiuruSpace object is equivalent with another object.
725       * @param o Object that we are comparing our KiuruSpace object with.
726       * @return True if objects are identical.
727       */  
728      public boolean equals(Object o) {
729        if (o instanceof KiuruSpace) {
730          KiuruSpace k = (KiuruSpace)(o);
731          if (getAddingNew() || k.getAddingNew()) 
732            return false; // new entities cannot be equal
733    
734          return (
735            (getSpaceId() == k.getSpaceId()) &&
736            (getName().equals(k.getName())) &&
737            (getOrganisationId() == k.getOrganisationId()) &&
738            (getIntSize() == k.getIntSize()) &&
739            (getType() == k.getType())
740          );
741        }
742        return false;
743      }
744      
745      /** Implementation of modify rights checking.
746       * Currently unofficial (non-organisation-related) spaces may by modified by
747       * anybody. Other spaces may be modified by secretary.
748       * @return true is user can modify entity.
749       * @see EntityHandler#hasModifyRight()
750       */
751      protected boolean doCheckModifyRight() {
752        if (getOrganisationId()==0) return true; // 0 is assumed to be equal to null.
753        return (getUser().getAccessRightLevelID() >= UseModule.ACCESS_RIGHT_LEVEL_SECRETARY);
754      }  
755      
756     
757      /** Implementation of parameter clearing.
758       * @see EntityHandler#clearEmptyParameters(HttpServletRequest)
759       * @param request <CODE>request</CODE>-object from the JSP-page.
760       */
761      protected void doClearEmptyParameters(HttpServletRequest request) {
762        if (KiuruString.isEmpty(request.getParameter("name"))) setName("");
763      }
764      
765      /** Retrieves record from database according to current Id field(s)
766       * value(s).
767       * <p>
768       * Id field(s) are defined in descendant classes. Method implements
769       * also user rights check, eg. if user has no right to retrieve
770       * the record, empty object is returned instead.
771       *
772       * @throws Exception if there is a problem with DB connection
773       */
774      public void getRecord() throws Exception {
775        assignSpaceFromDataBase();
776      }
777      
778      /** Saves record to database.
779       * <p>
780       * If field values are not valid, sets Ok property to false.
781       *
782       * @throws Exception if there is a problem with DB connection
783       */
784      public void postRecord() throws Exception {
785        putSpaceToDataBase();
786      }
787      
788      /** Default implementation of clearing action state. Descendant classes may
789       * override this.
790       * @see EntityHandler#resetActionState(HttpServletRequest)
791       * @param request The request-object of the JSP.
792       */
793      protected void doClearActionState(javax.servlet.http.HttpServletRequest request) {
794        if ((getEnumState()==KiuruHandler.NO_ACTION) && (!KiuruString.isEmpty(request.getParameter("spaceId")))) 
795          setEnumState(GET_RECORD); // if modifyrecord is not in URL, this simulates it.
796        else super.doClearActionState(request);
797      }
798    
799    }
800    /***************************************************************************************************
801     *               COPYRIGHT (C) KIURU -PROJECT GROUP
802     *               Limited rights granted. Please refer to license.
803     **************************************************************************************************/