001    /*
002     * The MIT License
003     * Copyright (c) 2012 Microsoft Corporation
004     *
005     * Permission is hereby granted, free of charge, to any person obtaining a copy
006     * of this software and associated documentation files (the "Software"), to deal
007     * in the Software without restriction, including without limitation the rights
008     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
009     * copies of the Software, and to permit persons to whom the Software is
010     * furnished to do so, subject to the following conditions:
011     *
012     * The above copyright notice and this permission notice shall be included in
013     * all copies or substantial portions of the Software.
014     *
015     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
016     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
017     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
018     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
019     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
020     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
021     * THE SOFTWARE.
022     */
023    
024    package microsoft.exchange.webservices.data.property.complex;
025    
026    import microsoft.exchange.webservices.data.core.EwsServiceXmlReader;
027    import microsoft.exchange.webservices.data.core.EwsServiceXmlWriter;
028    import microsoft.exchange.webservices.data.core.EwsUtilities;
029    import microsoft.exchange.webservices.data.core.ILazyMember;
030    import microsoft.exchange.webservices.data.core.LazyMember;
031    import microsoft.exchange.webservices.data.core.XmlElementNames;
032    import microsoft.exchange.webservices.data.core.enumeration.permission.folder.FolderPermissionLevel;
033    import microsoft.exchange.webservices.data.core.enumeration.permission.folder.FolderPermissionReadAccess;
034    import microsoft.exchange.webservices.data.core.enumeration.permission.PermissionScope;
035    import microsoft.exchange.webservices.data.core.enumeration.property.StandardUser;
036    import microsoft.exchange.webservices.data.core.enumeration.misc.XmlNamespace;
037    import microsoft.exchange.webservices.data.core.exception.service.local.ServiceLocalException;
038    import microsoft.exchange.webservices.data.core.exception.service.local.ServiceValidationException;
039    import org.apache.commons.logging.Log;
040    import org.apache.commons.logging.LogFactory;
041    
042    import java.util.ArrayList;
043    import java.util.HashMap;
044    import java.util.List;
045    import java.util.Map;
046    import java.util.Map.Entry;
047    
048    /**
049     * Represents a permission on a folder.
050     */
051    public final class FolderPermission extends ComplexProperty implements IComplexPropertyChangedDelegate {
052    
053      private static final Log LOG = LogFactory.getLog(FolderPermission.class);
054    
055      private static LazyMember<Map<FolderPermissionLevel, FolderPermission>>
056          defaultPermissions =
057          new LazyMember<Map<FolderPermissionLevel, FolderPermission>>(
058              new ILazyMember<Map<FolderPermissionLevel, FolderPermission>>() {
059                @Override
060                public Map<FolderPermissionLevel, FolderPermission>
061                createInstance() {
062                  Map<FolderPermissionLevel, FolderPermission> result =
063                      new HashMap<FolderPermissionLevel, FolderPermission>();
064    
065                  /** The default permissions. */
066                  FolderPermission permission = new FolderPermission();
067                  permission.canCreateItems = false;
068                  permission.canCreateSubFolders = false;
069                  permission.deleteItems = PermissionScope.None;
070                  permission.editItems = PermissionScope.None;
071                  permission.isFolderContact = false;
072                  permission.isFolderOwner = false;
073                  permission.isFolderVisible = false;
074                  permission.readItems = FolderPermissionReadAccess.None;
075    
076                  result.put(FolderPermissionLevel.None, permission);
077    
078                  permission = new FolderPermission();
079                  permission.canCreateItems = true;
080                  permission.canCreateSubFolders = false;
081                  permission.deleteItems = PermissionScope.None;
082                  permission.editItems = PermissionScope.None;
083                  permission.isFolderContact = false;
084                  permission.isFolderOwner = false;
085                  permission.isFolderVisible = true;
086                  permission.readItems = FolderPermissionReadAccess.None;
087    
088                  result.put(FolderPermissionLevel.Contributor, permission);
089    
090                  permission = new FolderPermission();
091                  permission.canCreateItems = false;
092                  permission.canCreateSubFolders = false;
093                  permission.deleteItems = PermissionScope.None;
094                  permission.editItems = PermissionScope.None;
095                  permission.isFolderContact = false;
096                  permission.isFolderOwner = false;
097                  permission.isFolderVisible = true;
098                  permission.readItems = FolderPermissionReadAccess.
099                      FullDetails;
100    
101                  result.put(FolderPermissionLevel.Reviewer, permission);
102    
103                  permission = new FolderPermission();
104                  permission.canCreateItems = true;
105                  permission.canCreateSubFolders = false;
106                  permission.deleteItems = PermissionScope.Owned;
107                  permission.editItems = PermissionScope.None;
108                  permission.isFolderContact = false;
109                  permission.isFolderOwner = false;
110                  permission.isFolderVisible = true;
111                  permission.readItems = FolderPermissionReadAccess.
112                      FullDetails;
113    
114                  result.put(FolderPermissionLevel.NoneditingAuthor,
115                      permission);
116    
117                  permission = new FolderPermission();
118                  permission.canCreateItems = true;
119                  permission.canCreateSubFolders = false;
120                  permission.deleteItems = PermissionScope.Owned;
121                  permission.editItems = PermissionScope.Owned;
122                  permission.isFolderContact = false;
123                  permission.isFolderOwner = false;
124                  permission.isFolderVisible = true;
125                  permission.readItems = FolderPermissionReadAccess.
126                      FullDetails;
127    
128                  result.put(FolderPermissionLevel.Author, permission);
129    
130                  permission = new FolderPermission();
131                  permission.canCreateItems = true;
132                  permission.canCreateSubFolders = true;
133                  permission.deleteItems = PermissionScope.Owned;
134                  permission.editItems = PermissionScope.Owned;
135                  permission.isFolderContact = false;
136                  permission.isFolderOwner = false;
137                  permission.isFolderVisible = true;
138                  permission.readItems = FolderPermissionReadAccess.
139                      FullDetails;
140    
141                  result.put(FolderPermissionLevel.PublishingAuthor,
142                      permission);
143    
144                  permission = new FolderPermission();
145                  permission.canCreateItems = true;
146                  permission.canCreateSubFolders = false;
147                  permission.deleteItems = PermissionScope.All;
148                  permission.editItems = PermissionScope.All;
149                  permission.isFolderContact = false;
150                  permission.isFolderOwner = false;
151                  permission.isFolderVisible = true;
152                  permission.readItems = FolderPermissionReadAccess.
153                      FullDetails;
154    
155                  result.put(FolderPermissionLevel.Editor, permission);
156    
157                  permission = new FolderPermission();
158                  permission.canCreateItems = true;
159                  permission.canCreateSubFolders = true;
160                  permission.deleteItems = PermissionScope.All;
161                  permission.editItems = PermissionScope.All;
162                  permission.isFolderContact = false;
163                  permission.isFolderOwner = false;
164                  permission.isFolderVisible = true;
165                  permission.readItems = FolderPermissionReadAccess.
166                      FullDetails;
167    
168                  result.put(FolderPermissionLevel.PublishingEditor,
169                      permission);
170    
171                  permission = new FolderPermission();
172                  permission.canCreateItems = true;
173                  permission.canCreateSubFolders = true;
174                  permission.deleteItems = PermissionScope.All;
175                  permission.editItems = PermissionScope.All;
176                  permission.isFolderContact = true;
177                  permission.isFolderOwner = true;
178                  permission.isFolderVisible = true;
179                  permission.readItems = FolderPermissionReadAccess.
180                      FullDetails;
181    
182                  result.put(FolderPermissionLevel.Owner, permission);
183    
184                  permission = new FolderPermission();
185                  permission.canCreateItems = false;
186                  permission.canCreateSubFolders = false;
187                  permission.deleteItems = PermissionScope.None;
188                  permission.editItems = PermissionScope.None;
189                  permission.isFolderContact = false;
190                  permission.isFolderOwner = false;
191                  permission.isFolderVisible = false;
192                  permission.readItems = FolderPermissionReadAccess.TimeOnly;
193    
194                  result.put(FolderPermissionLevel.FreeBusyTimeOnly,
195                      permission);
196    
197                  permission = new FolderPermission();
198                  permission.canCreateItems = false;
199                  permission.canCreateSubFolders = false;
200                  permission.deleteItems = PermissionScope.None;
201                  permission.editItems = PermissionScope.None;
202                  permission.isFolderContact = false;
203                  permission.isFolderOwner = false;
204                  permission.isFolderVisible = false;
205                  permission.readItems = FolderPermissionReadAccess.
206                      TimeAndSubjectAndLocation;
207    
208                  result
209                      .put(FolderPermissionLevel.
210                              FreeBusyTimeAndSubjectAndLocation,
211                          permission);
212                  return result;
213                }
214              });
215      //End Region
216    
217      /**
218       * Variants of pre-defined permission levels that Outlook also displays with
219       * the same levels.
220       */
221      private static LazyMember<List<FolderPermission>> levelVariants =
222          new LazyMember<List<FolderPermission>>(
223              new ILazyMember<List<FolderPermission>>() {
224                @Override
225                public List<FolderPermission> createInstance() {
226                  List<FolderPermission> results =
227                      new ArrayList<FolderPermission>();
228    
229                  FolderPermission permissionNone = FolderPermission.
230                      defaultPermissions
231                      .getMember().get(FolderPermissionLevel.None);
232                  FolderPermission permissionOwner = FolderPermission.
233                      defaultPermissions
234                      .getMember().get(FolderPermissionLevel.Owner);
235    
236                  // PermissionLevelNoneOption1
237                  FolderPermission permission;
238                  try {
239                    permission = (FolderPermission) permissionNone.clone();
240                    permission.isFolderVisible = true;
241                    results.add(permission);
242    
243                    // PermissionLevelNoneOption2
244                    permission = (FolderPermission) permissionNone.clone();
245                    permission.isFolderContact = true;
246                    results.add(permission);
247    
248                    // PermissionLevelNoneOption3
249                    permission = (FolderPermission) permissionNone.clone();
250                    permission.isFolderContact = true;
251                    permission.isFolderVisible = true;
252                    results.add(permission);
253    
254                    // PermissionLevelOwnerOption1
255                    permission = (FolderPermission) permissionOwner.clone();
256                    permission.isFolderContact = false;
257                    results.add(permission);
258    
259                  } catch (CloneNotSupportedException e) {
260                    LOG.error(e);
261                  }
262                  return results;
263                }
264              });
265    
266      /**
267       * The user id.
268       */
269      private UserId userId;
270    
271      /**
272       * The can create item.
273       */
274      private boolean canCreateItems;
275    
276      /**
277       * The can create sub folder.
278       */
279      private boolean canCreateSubFolders;
280    
281      /**
282       * The is folder owner.
283       */
284      private boolean isFolderOwner;
285    
286      /**
287       * The is folder visible.
288       */
289      private boolean isFolderVisible;
290    
291      /**
292       * The is folder contact.
293       */
294      private boolean isFolderContact;
295    
296      /**
297       * The edit item.
298       */
299      private PermissionScope editItems = PermissionScope.None;
300    
301      /**
302       * The delete item.
303       */
304      private PermissionScope deleteItems = PermissionScope.None;
305    
306      /**
307       * The read item.
308       */
309      private FolderPermissionReadAccess readItems = FolderPermissionReadAccess.None;
310    
311      /**
312       * The permission level.
313       */
314      private FolderPermissionLevel permissionLevel = FolderPermissionLevel.None;
315    
316      /**
317       * Determines whether the specified folder permission is the same as this
318       * one. The comparison does not take UserId and PermissionLevel into
319       * consideration.
320       *
321       * @param permission the permission
322       * @return True is the specified folder permission is equal to this one,
323       * false otherwise.
324       */
325      private boolean isEqualTo(FolderPermission permission) {
326    
327        return this.canCreateItems == permission.canCreateItems &&
328            this.canCreateSubFolders == permission.canCreateSubFolders &&
329            this.isFolderContact == permission.isFolderContact &&
330            this.isFolderVisible == permission.isFolderVisible &&
331            this.isFolderOwner == permission.isFolderOwner &&
332            this.editItems == permission.editItems &&
333            this.deleteItems == permission.deleteItems &&
334            this.readItems == permission.readItems;
335      }
336    
337      /**
338       * Create a copy of this FolderPermission instance.
339       *
340       * @return Clone of this instance.
341       */
342            /*
343             * private FolderPermission Clone() throws CloneNotSupportedException {
344             * return (FolderPermission)this.clone(); }
345             */
346    
347      /**
348       * Determines the permission level of this folder permission based on its
349       * individual settings, and sets the PermissionLevel property accordingly.
350       */
351      private void AdjustPermissionLevel() {
352        for (Entry<FolderPermissionLevel, FolderPermission> keyValuePair : defaultPermissions
353            .getMember().entrySet()) {
354          if (this.isEqualTo(keyValuePair.getValue())) {
355            this.permissionLevel = keyValuePair.getKey();
356            return;
357          }
358        }
359        this.permissionLevel = FolderPermissionLevel.Custom;
360      }
361    
362      /**
363       * Copies the values of the individual permissions of the specified folder
364       * permission to this folder permissions.
365       *
366       * @param permission the permission
367       */
368      private void AssignIndividualPermissions(FolderPermission permission) {
369        this.canCreateItems = permission.canCreateItems;
370        this.canCreateSubFolders = permission.canCreateSubFolders;
371        this.isFolderContact = permission.isFolderContact;
372        this.isFolderOwner = permission.isFolderOwner;
373        this.isFolderVisible = permission.isFolderVisible;
374        this.editItems = permission.editItems;
375        this.deleteItems = permission.deleteItems;
376        this.readItems = permission.readItems;
377      }
378    
379      /**
380       * Initializes a new instance of the FolderPermission class.
381       */
382      public FolderPermission() {
383        super();
384        this.userId = new UserId();
385      }
386    
387      /**
388       * Initializes a new instance of the FolderPermission class.
389       *
390       * @param userId          the user id
391       * @param permissionLevel the permission level
392       * @throws Exception the exception
393       */
394      public FolderPermission(UserId userId,
395          FolderPermissionLevel permissionLevel)
396          throws Exception {
397        EwsUtilities.validateParam(userId, "userId");
398    
399        this.userId = userId;
400        this.permissionLevel = permissionLevel;
401      }
402    
403      /**
404       * Initializes a new instance of the FolderPermission class.
405       *
406       * @param primarySmtpAddress the primary smtp address
407       * @param permissionLevel    the permission level
408       */
409      public FolderPermission(String primarySmtpAddress,
410          FolderPermissionLevel permissionLevel) {
411        this.userId = new UserId(primarySmtpAddress);
412        this.permissionLevel = permissionLevel;
413      }
414    
415      /**
416       * Initializes a new instance of the FolderPermission class.
417       *
418       * @param standardUser    the standard user
419       * @param permissionLevel the permission level
420       */
421      public FolderPermission(StandardUser standardUser,
422          FolderPermissionLevel permissionLevel) {
423        this.userId = new UserId(standardUser);
424        this.permissionLevel = permissionLevel;
425      }
426    
427      /**
428       * Validates this instance.
429       *
430       * @param isCalendarFolder the is calendar folder
431       * @param permissionIndex  the permission index
432       * @throws ServiceValidationException the service validation exception
433       * @throws ServiceLocalException      the service local exception
434       */
435      void validate(boolean isCalendarFolder, int permissionIndex)
436          throws ServiceValidationException, ServiceLocalException {
437        // Check UserId
438        if (!this.userId.isValid()) {
439          throw new ServiceValidationException(String.format(
440              "The UserId in the folder permission at index %d is invalid. "
441              + "The StandardUser, PrimarySmtpAddress, or SID property must be set.", permissionIndex));
442        }
443    
444        // If this permission is to be used for a non-calendar folder make sure
445        // that read access and permission level aren't set to Calendar-only
446        // values
447        if (!isCalendarFolder) {
448          if ((this.readItems == FolderPermissionReadAccess.TimeAndSubjectAndLocation)
449              || (this.readItems == FolderPermissionReadAccess.
450              TimeOnly)) {
451            throw new ServiceLocalException(String.format(
452                "Permission read access value %s cannot be used with non-calendar folder.",
453                this.readItems));
454          }
455    
456          if ((this.permissionLevel == FolderPermissionLevel.FreeBusyTimeAndSubjectAndLocation)
457              || (this.permissionLevel == FolderPermissionLevel.
458              FreeBusyTimeOnly)) {
459            throw new ServiceLocalException(String.format(
460                "Permission level value %s cannot be used with non-calendar folder.",
461                this.permissionLevel));
462          }
463        }
464      }
465    
466      /**
467       * Gets the Id of the user the permission applies to.
468       *
469       * @return the user id
470       */
471    
472      public UserId getUserId() {
473        return this.userId;
474      }
475    
476      /**
477       * Sets the user id.
478       *
479       * @param value the new user id
480       */
481      public void setUserId(UserId value) {
482        if (this.userId != null) {
483          this.userId.removeChangeEvent(this);
484        }
485    
486        if (this.canSetFieldValue(this.userId, value)) {
487          userId = value;
488          this.changed();
489        }
490        if (this.userId != null) {
491          this.userId.addOnChangeEvent(this);
492        }
493      }
494    
495      /*
496       * (non-Javadoc)
497       *
498       * @see
499       * microsoft.exchange.webservices.ComplexPropertyChangedDelegateInterface
500       * #complexPropertyChanged(microsoft.exchange.webservices.ComplexProperty)
501       */
502      @Override
503      public void complexPropertyChanged(ComplexProperty complexProperty) {
504        this.propertyChanged(complexProperty);
505      }
506    
507      /**
508       * Property was changed.
509       *
510       * @param complexProperty the complex property
511       */
512      private void propertyChanged(ComplexProperty complexProperty) {
513        this.changed();
514      }
515    
516      /**
517       * Gets  a value indicating whether the user can create new item.
518       *
519       * @return the can create item
520       */
521      public boolean getCanCreateItems() {
522        return this.canCreateItems;
523      }
524    
525      /**
526       * Sets the can create item.
527       *
528       * @param value the new can create item
529       */
530      public void setCanCreateItems(boolean value) {
531        if (this.canSetFieldValue(this.canCreateItems, value)) {
532          this.canCreateItems = value;
533          this.changed();
534        }
535        this.AdjustPermissionLevel();
536      }
537    
538      /**
539       * Gets  a value indicating whether the user can create
540       * sub-folder.
541       *
542       * @return the can create sub folder
543       */
544      public boolean getCanCreateSubFolders() {
545        return this.canCreateSubFolders;
546      }
547    
548      /**
549       * Sets the can create sub folder.
550       *
551       * @param value the new can create sub folder
552       */
553      public void setCanCreateSubFolders(boolean value) {
554        if (this.canSetFieldValue(this.canCreateSubFolders, value)) {
555          this.canCreateSubFolders = value;
556          this.changed();
557        }
558        this.AdjustPermissionLevel();
559      }
560    
561      /**
562       * Gets a value indicating whether the user owns the folder.
563       *
564       * @return the checks if is folder owner
565       */
566      public boolean getIsFolderOwner() {
567        return this.isFolderOwner;
568      }
569    
570      /**
571       * Sets the checks if is folder owner.
572       *
573       * @param value the new checks if is folder owner
574       */
575      public void setIsFolderOwner(boolean value) {
576        if (this.canSetFieldValue(this.isFolderOwner, value)) {
577          this.isFolderOwner = value;
578          this.changed();
579        }
580        this.AdjustPermissionLevel();
581      }
582    
583      /**
584       * Gets a value indicating whether the folder is visible to the
585       * user.
586       *
587       * @return the checks if is folder visible
588       */
589      public boolean getIsFolderVisible() {
590        return this.isFolderVisible;
591      }
592    
593      /**
594       * Sets the checks if is folder visible.
595       *
596       * @param value the new checks if is folder visible
597       */
598      public void setIsFolderVisible(boolean value) {
599        if (this.canSetFieldValue(this.isFolderVisible, value)) {
600          this.isFolderVisible = value;
601          this.changed();
602        }
603        this.AdjustPermissionLevel();
604      }
605    
606      /**
607       * Gets  a value indicating whether the user is a contact for the
608       * folder.
609       *
610       * @return the checks if is folder contact
611       */
612      public boolean getIsFolderContact() {
613        return this.isFolderContact;
614      }
615    
616      /**
617       * Sets the checks if is folder contact.
618       *
619       * @param value the new checks if is folder contact
620       */
621      public void setIsFolderContact(boolean value) {
622        if (this.canSetFieldValue(this.isFolderContact, value)) {
623          this.isFolderContact = value;
624          this.changed();
625        }
626        this.AdjustPermissionLevel();
627      }
628    
629      /**
630       * Gets  a value indicating if/how the user can edit existing
631       * item.
632       *
633       * @return the edits the item
634       */
635      public PermissionScope getEditItems() {
636        return this.editItems;
637      }
638    
639      /**
640       * Sets the edits the item.
641       *
642       * @param value the new edits the item
643       */
644      public void setEditItems(PermissionScope value) {
645        if (this.canSetFieldValue(this.editItems, value)) {
646          this.editItems = value;
647          this.changed();
648        }
649        this.AdjustPermissionLevel();
650      }
651    
652      /**
653       * Gets  a value indicating if/how the user can delete existing
654       * item.
655       *
656       * @return the delete item
657       */
658      public PermissionScope getDeleteItems() {
659        return this.deleteItems;
660      }
661    
662      /**
663       * Sets the delete item.
664       *
665       * @param value the new delete item
666       */
667      public void setDeleteItems(PermissionScope value) {
668        if (this.canSetFieldValue(this.deleteItems, value)) {
669          this.deleteItems = value;
670          this.changed();
671        }
672        this.AdjustPermissionLevel();
673      }
674    
675      /**
676       * Gets  the read item access permission.
677       *
678       * @return the read item
679       */
680      public FolderPermissionReadAccess getReadItems() {
681        return this.readItems;
682      }
683    
684      /**
685       * Sets the read item.
686       *
687       * @param value the new read item
688       */
689      public void setReadItems(FolderPermissionReadAccess value) {
690        if (this.canSetFieldValue(this.readItems, value)) {
691          this.readItems = value;
692          this.changed();
693        }
694        this.AdjustPermissionLevel();
695      }
696    
697      /**
698       * Gets  the permission level.
699       *
700       * @return the permission level
701       */
702      public FolderPermissionLevel getPermissionLevel() {
703        return this.permissionLevel;
704      }
705    
706      /**
707       * Sets the permission level.
708       *
709       * @param value the new permission level
710       * @throws ServiceLocalException the service local exception
711       */
712      public void setPermissionLevel(FolderPermissionLevel value)
713          throws ServiceLocalException {
714        if (this.permissionLevel != value) {
715          if (value == FolderPermissionLevel.Custom) {
716            throw new ServiceLocalException(
717                "The PermissionLevel property can't be set to FolderPermissionLevel.Custom. "
718                + "To define a custom permission, set its individual property to the values you want.");
719          }
720    
721          this.AssignIndividualPermissions(defaultPermissions.getMember()
722              .get(value));
723          if (this.canSetFieldValue(this.permissionLevel, value)) {
724            this.permissionLevel = value;
725            this.changed();
726          }
727        }
728      }
729    
730      /**
731       * Gets the permission level that Outlook would display for this folder
732       * permission.
733       *
734       * @return the display permission level
735       */
736      public FolderPermissionLevel getDisplayPermissionLevel() {
737        // If permission level is set to Custom, see if there's a variant
738        // that Outlook would map to the same permission level.
739        if (this.permissionLevel == FolderPermissionLevel.Custom) {
740          for (FolderPermission variant : FolderPermission.levelVariants
741              .getMember()) {
742            if (this.isEqualTo(variant)) {
743              return variant.getPermissionLevel();
744            }
745          }
746        }
747    
748        return this.permissionLevel;
749      }
750    
751      /**
752       * Tries to read element from XML.
753       *
754       * @param reader the reader
755       * @return True if element was read.
756       * @throws Exception the exception
757       */
758      public boolean tryReadElementFromXml(EwsServiceXmlReader reader)
759          throws Exception {
760        if (reader.getLocalName().equalsIgnoreCase(XmlElementNames.UserId)) {
761          this.userId = new UserId();
762          this.userId.loadFromXml(reader, reader.getLocalName());
763          return true;
764        } else if (reader.getLocalName().equalsIgnoreCase(
765            XmlElementNames.CanCreateItems)) {
766          this.canCreateItems = reader.readValue(Boolean.class);
767          return true;
768        } else if (reader.getLocalName().equalsIgnoreCase(
769            XmlElementNames.CanCreateSubFolders)) {
770          this.canCreateSubFolders = reader.readValue(Boolean.class);
771          return true;
772        } else if (reader.getLocalName().equalsIgnoreCase(
773            XmlElementNames.IsFolderOwner)) {
774          this.isFolderOwner = reader.readValue(Boolean.class);
775          return true;
776        } else if (reader.getLocalName().equalsIgnoreCase(
777            XmlElementNames.IsFolderVisible)) {
778          this.isFolderVisible = reader.readValue(Boolean.class);
779          return true;
780        } else if (reader.getLocalName().equalsIgnoreCase(
781            XmlElementNames.IsFolderContact)) {
782          this.isFolderContact = reader.readValue(Boolean.class);
783          return true;
784        } else if (reader.getLocalName().equalsIgnoreCase(
785            XmlElementNames.EditItems)) {
786          this.editItems = reader.readValue(PermissionScope.class);
787          return true;
788        } else if (reader.getLocalName().equalsIgnoreCase(
789            XmlElementNames.DeleteItems)) {
790          this.deleteItems = reader.readValue(PermissionScope.class);
791          return true;
792        } else if (reader.getLocalName().equalsIgnoreCase(
793            XmlElementNames.ReadItems)) {
794          this.readItems = reader.readValue(FolderPermissionReadAccess.class);
795          return true;
796        } else if (reader.getLocalName().equalsIgnoreCase(
797            XmlElementNames.PermissionLevel)
798            || reader.getLocalName().equalsIgnoreCase(
799            XmlElementNames.CalendarPermissionLevel)) {
800          this.permissionLevel = reader
801              .readValue(FolderPermissionLevel.class);
802          return true;
803        } else {
804          return false;
805        }
806      }
807    
808      /**
809       * Loads from XML.
810       *
811       * @param reader         the reader
812       * @param xmlNamespace   the xml namespace
813       * @param xmlElementName the xml element name
814       * @throws Exception the exception
815       */
816      public void loadFromXml(EwsServiceXmlReader reader, XmlNamespace xmlNamespace, String xmlElementName) throws Exception {
817        super.loadFromXml(reader, xmlNamespace, xmlElementName);
818    
819        this.AdjustPermissionLevel();
820      }
821    
822      /**
823       * Writes elements to XML.
824       *
825       * @param writer           the writer
826       * @param isCalendarFolder the is calendar folder
827       * @throws Exception the exception
828       */
829      protected void writeElementsToXml(EwsServiceXmlWriter writer,
830          boolean isCalendarFolder) throws Exception {
831        if (this.userId != null) {
832          this.userId.writeToXml(writer, XmlElementNames.UserId);
833        }
834    
835        if (this.permissionLevel == FolderPermissionLevel.Custom) {
836          writer.writeElementValue(XmlNamespace.Types,
837              XmlElementNames.CanCreateItems, this.canCreateItems);
838    
839          writer.writeElementValue(XmlNamespace.Types,
840              XmlElementNames.CanCreateSubFolders,
841              this.canCreateSubFolders);
842    
843          writer.writeElementValue(XmlNamespace.Types,
844              XmlElementNames.IsFolderOwner, this.isFolderOwner);
845    
846          writer.writeElementValue(XmlNamespace.Types,
847              XmlElementNames.IsFolderVisible, this.isFolderVisible);
848    
849          writer.writeElementValue(XmlNamespace.Types,
850              XmlElementNames.IsFolderContact, this.isFolderContact);
851    
852          writer.writeElementValue(XmlNamespace.Types,
853              XmlElementNames.EditItems, this.editItems);
854    
855          writer.writeElementValue(XmlNamespace.Types,
856              XmlElementNames.DeleteItems, this.deleteItems);
857    
858          writer.writeElementValue(XmlNamespace.Types,
859              XmlElementNames.ReadItems, this.readItems);
860        }
861    
862        writer
863            .writeElementValue(
864                XmlNamespace.Types,
865                isCalendarFolder ? XmlElementNames.
866                    CalendarPermissionLevel
867                    : XmlElementNames.PermissionLevel,
868                this.permissionLevel);
869      }
870    
871      /**
872       * Writes to XML.
873       *
874       * @param writer           the writer
875       * @param xmlElementName   the xml element name
876       * @param isCalendarFolder the is calendar folder
877       * @throws Exception the exception
878       */
879      protected void writeToXml(EwsServiceXmlWriter writer,
880          String xmlElementName, boolean isCalendarFolder) throws Exception {
881        writer.writeStartElement(this.getNamespace(), xmlElementName);
882        this.writeAttributesToXml(writer);
883        this.writeElementsToXml(writer, isCalendarFolder);
884        writer.writeEndElement();
885      }
886    }