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
024package microsoft.exchange.webservices.data.property.complex;
025
026import microsoft.exchange.webservices.data.core.EwsServiceXmlReader;
027import microsoft.exchange.webservices.data.core.EwsServiceXmlWriter;
028import microsoft.exchange.webservices.data.core.EwsUtilities;
029import microsoft.exchange.webservices.data.core.ILazyMember;
030import microsoft.exchange.webservices.data.core.LazyMember;
031import microsoft.exchange.webservices.data.core.XmlElementNames;
032import microsoft.exchange.webservices.data.core.enumeration.permission.folder.FolderPermissionLevel;
033import microsoft.exchange.webservices.data.core.enumeration.permission.folder.FolderPermissionReadAccess;
034import microsoft.exchange.webservices.data.core.enumeration.permission.PermissionScope;
035import microsoft.exchange.webservices.data.core.enumeration.property.StandardUser;
036import microsoft.exchange.webservices.data.core.enumeration.misc.XmlNamespace;
037import microsoft.exchange.webservices.data.core.exception.service.local.ServiceLocalException;
038import microsoft.exchange.webservices.data.core.exception.service.local.ServiceValidationException;
039import org.apache.commons.logging.Log;
040import org.apache.commons.logging.LogFactory;
041
042import java.util.ArrayList;
043import java.util.HashMap;
044import java.util.List;
045import java.util.Map;
046import java.util.Map.Entry;
047
048/**
049 * Represents a permission on a folder.
050 */
051public 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}