All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.internet2.middleware.grouper.grouperUi.beans.attributeUpdate.AttributeUpdateRequestContainer Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright 2012 Internet2
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
/*
 * @author mchyzer
 * $Id: SimpleMembershipUpdateContainer.java,v 1.4 2009-11-02 08:50:40 mchyzer Exp $
 */
package edu.internet2.middleware.grouper.grouperUi.beans.attributeUpdate;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;

import edu.internet2.middleware.grouper.GrouperSession;
import edu.internet2.middleware.grouper.Member;
import edu.internet2.middleware.grouper.MemberFinder;
import edu.internet2.middleware.grouper.attr.AttributeDef;
import edu.internet2.middleware.grouper.attr.assign.AttributeAssignAction;
import edu.internet2.middleware.grouper.attr.assign.AttributeAssignType;
import edu.internet2.middleware.grouper.attr.value.AttributeAssignValue;
import edu.internet2.middleware.grouper.grouperUi.beans.api.GuiAttributeAssign;
import edu.internet2.middleware.grouper.grouperUi.beans.api.GuiAttributeDef;
import edu.internet2.middleware.grouper.grouperUi.beans.api.GuiMember;
import edu.internet2.middleware.grouper.privs.PrivilegeSubjectContainer;
import edu.internet2.middleware.grouper.ui.GrouperUiFilter;
import edu.internet2.middleware.grouper.ui.util.GrouperUiConfig;
import edu.internet2.middleware.grouper.ui.util.MapWrapper;
import edu.internet2.middleware.grouper.util.GrouperUtil;



/**
 * bean for simple attribute update.  holds all state for this module
 */
@SuppressWarnings("serial")
public class AttributeUpdateRequestContainer implements Serializable {

  /**
   * attribute assign value we are editing 
   */
  private AttributeAssignValue attributeAssignValue = null;
  
  /**
   * 
   * @return value
   */
  public AttributeAssignValue getAttributeAssignValue() {
    return this.attributeAssignValue;
  }

  /**
   * 
   * @param attributeAssignValue1
   */
  public void setAttributeAssignValue(AttributeAssignValue attributeAssignValue1) {
    this.attributeAssignValue = attributeAssignValue1;
  }

  /** gui attribute assign */
  private GuiAttributeAssign guiAttributeAssign = null;
  
  /** gui attribute assign on assignment */
  private GuiAttributeAssign guiAttributeAssignAssign = null;
  
  
  
  /**
   * gui attribute assign on assignment
   * @return gui attribute assign on assignment
   */
  public GuiAttributeAssign getGuiAttributeAssignAssign() {
    return this.guiAttributeAssignAssign;
  }

  /**
   * gui attribute assign on assignment
   * @param guiAttributeAssignAssign1
   */
  public void setGuiAttributeAssignAssign(GuiAttributeAssign guiAttributeAssignAssign1) {
    this.guiAttributeAssignAssign = guiAttributeAssignAssign1;
  }

  /** if we are assigning to a group, folder, etc */
  private AttributeAssignType attributeAssignType;
  
  /** if we are assigning to a group, folder, etc, this is the non underlying assign type */
  private AttributeAssignType attributeAssignAssignType;
  
  /**
   * if we are assigning to a group, folder, etc, this is the non underlying assign type
   * @return assign type
   */
  public AttributeAssignType getAttributeAssignAssignType() {
    return this.attributeAssignAssignType;
  }

  /**
   * if we are assigning to a group, folder, etc, this is the non underlying assign type
   * @param attributeAssignAssignType1
   */
  public void setAttributeAssignAssignType(AttributeAssignType attributeAssignAssignType1) {
    this.attributeAssignAssignType = attributeAssignAssignType1;
  }

  /**
   * if we are assigning to a group, folder, etc
   * @return type
   */
  public AttributeAssignType getAttributeAssignType() {
    return this.attributeAssignType;
  }

  /**
   * enabledOnly, disabledOnly, or all (null)
   */
  private Boolean enabledDisabled = Boolean.TRUE;

  /** 
   * return enabledOnly, disabledOnly, or all (null)
   * @return enabledOnly, disabledOnly, or all (null)
   */
  public Boolean getEnabledDisabled() {
    return this.enabledDisabled;
  }

  /**
   * enabledOnly, disabledOnly, or all (null)
   * @param theEnabledDisabled
   */
  public void setEnabledDisabled(Boolean theEnabledDisabled) {
    this.enabledDisabled = theEnabledDisabled;
  }

  /**
   * label for type
   * @return label for type
   */
  public String getAttributeAssignTypeLabelKey() {
    
    switch (this.getAttributeAssignType()) {

      case group:
      {
        return "simpleAttributeUpdate.assignHeaderOwnerGroup";
      }
      case stem:
      {
        return "simpleAttributeUpdate.assignHeaderOwnerFolder";
      }
      case member:
      {
        return "simpleAttributeUpdate.assignHeaderOwnerMember";
      }
      case imm_mem:
      {
        return "simpleAttributeUpdate.assignHeaderOwnerMembership";
      }
      case any_mem:
      {
        return "simpleAttributeUpdate.assignHeaderOwnerMembership";
      }
      case attr_def:
      {
        return "simpleAttributeUpdate.assignHeaderOwnerAttributeDefinition";
      }
      
      default:
        throw new RuntimeException("Not expecting attribute assign type: " + this.getAttributeAssignType());
    }
    
  }
  
  /**
   * if we are assigning to a group, folder, etc
   * @param attributeAssignType1
   */
  public void setAttributeAssignType(AttributeAssignType attributeAssignType1) {
    this.attributeAssignType = attributeAssignType1;
  }

  /** attribute def we are editing */
  private AttributeDef attributeDefToEdit;
  
  /** gui attribute def we are editing */
  private GuiAttributeDef guiAttributeDefToEdit;
  
  /** list of actions for the attribute def */
  private List actions;

  /** list of actions which can be added as an action which implies */
  private List newActionsCanImply;

  /** list of actions which can be added as an action which impliedBy */
  private List newActionsCanImpliedBy;

  /** list of actions that imply this action */
  private List actionsThatImply;
  
  /** list of actions implied by this action */
  private List actionsImpliedBy;
  
  /** privilege subject containers */
  private Set privilegeSubjectContainers;
  
  /** attribute assigns */
  private List guiAttributeAssigns;
  
  /**
   * attribute assigns
   * @return the attribute assigns
   */
  public List getGuiAttributeAssigns() {
    return this.guiAttributeAssigns;
  }

  /**
   * attribute assigns
   * @param attributeAssigns1
   */
  public void setGuiAttributeAssigns(List attributeAssigns1) {
    this.guiAttributeAssigns = attributeAssigns1;
  }

  /** gui members */
  private List privilegeSubjectContainerGuiMembers;

  /** additional gui members to view or assign */
  private List privilegeAdditionalGuiMembers;
  
  /**
   * additional gui members to view or assign
   * @return additional gui members to view or assign
   */
  public List getPrivilegeAdditionalGuiMembers() {
    return this.privilegeAdditionalGuiMembers;
  }

  /**
   * calculate based on request object, and return list, unless it is already calculated
   * @return the list
   */
  public List privilegeAdditionalGuiMembers() {
    if (this.privilegeAdditionalGuiMembers == null) {
      this.privilegeAdditionalGuiMembers = new ArrayList();
      
      HttpServletRequest httpServletRequest = GrouperUiFilter.retrieveHttpServletRequest();
      
      //max of 200, no endless loops
      for (int i=0;i<200;i++) {
        
        String memberId = httpServletRequest.getParameter("additionalMemberId_" + i);
        if (StringUtils.isBlank(memberId)) {
          break;
        }
        
        Member member = MemberFinder.findByUuid(GrouperSession.staticGrouperSession(), memberId, true);
        
        this.privilegeAdditionalGuiMembers.add(new GuiMember(member));
        
      }
    }
    
    return this.privilegeAdditionalGuiMembers;
    
  }
  
  /**
   * additional gui members to view or assign
   * @param privilegeAdditionalGuiMembers1
   */
  public void setPrivilegeAdditionalGuiMembers(List privilegeAdditionalGuiMembers1) {
    this.privilegeAdditionalGuiMembers = privilegeAdditionalGuiMembers1;
  }

  /**
   * gui members
   * @return gui members
   */
  public List getPrivilegeSubjectContainerGuiMembers() {
    return this.privilegeSubjectContainerGuiMembers;
  }

  /**
   * gui members
   * @param privilegeSubjectContainerGuiMembers1
   */
  public void setPrivilegeSubjectContainerGuiMembers(
      List privilegeSubjectContainerGuiMembers1) {
    this.privilegeSubjectContainerGuiMembers = privilegeSubjectContainerGuiMembers1;
  }

  /**
   * privilege subject containers
   * @return privilege subject containers
   */
  public Set getPrivilegeSubjectContainers() {
    return this.privilegeSubjectContainers;
  }

  /**
   * privilege subject containers
   * @param privilegeSubjectContainers1
   */
  public void setPrivilegeSubjectContainers(
      Set privilegeSubjectContainers1) {
    this.privilegeSubjectContainers = privilegeSubjectContainers1;
  }

  /**
   * list of actions implied by this action
   * @return actions
   */
  public List getActionsImpliedBy() {
    return this.actionsImpliedBy;
  }

  /**
   * list of actions implied by this action
   * @param actionsImpliedBy1
   */
  public void setActionsImpliedBy(List actionsImpliedBy1) {
    this.actionsImpliedBy = actionsImpliedBy1;
  }

  /** list of actions implied by this action immediately */
  private List actionsImpliedByImmediate;
  
  /**
   * list of actions implied by this action immediately
   * @return actions
   */
  public List getActionsImpliedByImmediate() {
    return this.actionsImpliedByImmediate;
  }

  /**
   * list of actions implied by this action immediately
   * @param actionsImpliedByImmediate1
   */
  public void setActionsImpliedByImmediate(List actionsImpliedByImmediate1) {
    this.actionsImpliedByImmediate = actionsImpliedByImmediate1;
  }

  /** list of actions that imply this action immediately */
  private List actionsThatImplyImmediate;
  
  /**
   * list of actions that imply this action immediately
   * @return actions
   */
  public List getActionsThatImplyImmediate() {
    return this.actionsThatImplyImmediate;
  }

  /**
   * list of actions that imply this action immediately
   * @param actionsThatImplyImmediate1
   */
  public void setActionsThatImplyImmediate(List actionsThatImplyImmediate1) {
    this.actionsThatImplyImmediate = actionsThatImplyImmediate1;
  }

  /**
   * list of actions that imply this action
   * @return the actions
   */
  public List getActionsThatImply() {
    return this.actionsThatImply;
  }

  /**
   * list of actions that imply this action
   * @param actionsThatImply1
   */
  public void setActionsThatImply(List actionsThatImply1) {
    this.actionsThatImply = actionsThatImply1;
  }

  /**
   * list of actions which can be added as an action which impliedBy
   * @return actions
   */
  public List getNewActionsCanImpliedBy() {
    return this.newActionsCanImpliedBy;
  }

  /**
   * list of actions which can be added as an action which impliedBy
   * @param newActionsCanImpliedBy1
   */
  public void setNewActionsCanImpliedBy(List newActionsCanImpliedBy1) {
    this.newActionsCanImpliedBy = newActionsCanImpliedBy1;
  }

  /**
   * list of actions which can be added as an action which implies
   * @return actions
   */
  public List getNewActionsCanImply() {
    return this.newActionsCanImply;
  }

  /**
   * list of actions which can be added as an action which implies
   * @param newActionsCanImply1
   */
  public void setNewActionsCanImply(List newActionsCanImply1) {
    this.newActionsCanImply = newActionsCanImply1;
  }

  /** action we are editing */
  private String action;
  
  /**
   * action we are editing
   * @return the action
   */
  public String getAction() {
    return this.action;
  }
  
  /**
   * action we are editing
   * @param action1 the action to set
   */
  public void setAction(String action1) {
    this.action = action1;
  }
  
  /** attribute assign action we are editing */
  private AttributeAssignAction attributeAssignAction;
  
  /**
   * attribute assign action we are editing
   * @return the attributeAssignAction
   */
  public AttributeAssignAction getAttributeAssignAction() {
    return this.attributeAssignAction;
  }
  
  /**
   * attribute assign action we are editing
   * @param attributeAssignAction1 the action to set
   */
  public void setAttributeAssignAction(AttributeAssignAction attributeAssignAction1) {
    this.attributeAssignAction = attributeAssignAction1;
  }

  /**
   * list of actions for the attribute def
   * @return actions
   */
  public List getActions() {
    return this.actions;
  }

  /**
   * list of actions for the attribute def
   * @param actions1
   */
  public void setActions(List actions1) {
    this.actions = actions1;
  }

  /**
   * attribute def we are editing
   * @return the attribute def
   */
  public AttributeDef getAttributeDefToEdit() {
    return this.attributeDefToEdit;
  }

  /**
   * attribute def we are editing
   * @param attributeDefToEdit1
   */
  public void setAttributeDefToEdit(AttributeDef attributeDefToEdit1) {
    this.attributeDefToEdit = attributeDefToEdit1;
  }
  
  /**
   * gui attribute def we are editing
   * @return the gui attribute def
   */
  public GuiAttributeDef getGuiAttributeDefToEdit() {
    return this.guiAttributeDefToEdit;
  }

  /**
   * gui attribute def we are editing
   * @param guiAttributeDefToEdit1
   */
  public void setGuiAttributeDefToEdit(GuiAttributeDef guiAttributeDefToEdit1) {
    this.guiAttributeDefToEdit = guiAttributeDefToEdit1;
  }

  /** if this is a create as opposed to update */
  private boolean create;
  
  
  
  /**
   * if this is a create as opposed to update
   * @return if create
   */
  public boolean isCreate() {
    return this.create;
  }

  /**
   * if this is a create as opposed to update
   * @param create1
   */
  public void setCreate(boolean create1) {
    this.create = create1;
  }

  /**
   * store to session scope
   */
  public void storeToRequest() {
    HttpServletRequest httpServletRequest = GrouperUiFilter.retrieveHttpServletRequest();
    httpServletRequest.setAttribute("attributeUpdateRequestContainer", this);
  }

  /**
   * retrieveFromSession, cannot be null
   * @return the app state in request scope
   */
  public static AttributeUpdateRequestContainer retrieveFromRequestOrCreate() {
    HttpServletRequest httpServletRequest = GrouperUiFilter.retrieveHttpServletRequest();
    AttributeUpdateRequestContainer attributeUpdateRequestContainer = 
      (AttributeUpdateRequestContainer)httpServletRequest.getAttribute("attributeUpdateRequestContainer");
    if (attributeUpdateRequestContainer == null) {
      attributeUpdateRequestContainer = new AttributeUpdateRequestContainer();
      attributeUpdateRequestContainer.storeToRequest();
    }
    return attributeUpdateRequestContainer;
  }

  /** 
   * text bean
   * @return text bean
   */
  public AttributeUpdateText getText() {
    return AttributeUpdateText.retrieveSingleton();
  }

  /**
   * if should show indirect privileges
   * @return true if should show
   */
  public boolean isShowIndirectPrivilegesComputed() {

    HttpServletRequest httpServletRequest = GrouperUiFilter.retrieveHttpServletRequest();

    String showIndirectPrivilegesString = httpServletRequest.getParameter("showIndirectPrivileges");
    
    return GrouperUtil.booleanValue(showIndirectPrivilegesString, false);
  }
  
  /**
   * if this is public
   * @return if we should show the privilege header
   */
  public Map getAllowAll() {
    
    return new MapWrapper() {

      @Override
      public Boolean get(Object key) {
        String priv = (String)key;
        if (StringUtils.equals(priv, "attrView")) {
          return AttributeUpdateRequestContainer.this.isAllowAllView();
        }
        if (StringUtils.equals(priv, "attrRead")) {
          return AttributeUpdateRequestContainer.this.isAllowAllRead();
        }
        if (StringUtils.equals(priv, "attrAdmin")) {
          return AttributeUpdateRequestContainer.this.isAllowAllAdmin();
        }
        if (StringUtils.equals(priv, "attrUpdate")) {
          return AttributeUpdateRequestContainer.this.isAllowAllUpdate();
        }
        if (StringUtils.equals(priv, "attrOptin")) {
          return AttributeUpdateRequestContainer.this.isAllowAllOptin();
        }
        if (StringUtils.equals(priv, "attrOptout")) {
          return AttributeUpdateRequestContainer.this.isAllowAllOptout();
        }
        if (StringUtils.equals(priv, "attrDefAttrRead")) {
          return AttributeUpdateRequestContainer.this.isAllowAllAttrDefAttrRead();
        }
        if (StringUtils.equals(priv, "attrDefAttrUpdate")) {
          return AttributeUpdateRequestContainer.this.isAllowAllAttrDefAttrUpdate();
        }
        throw new RuntimeException("Not expecting string");
      }
      
    };
    
  }

  /**
   * map wrapper
   */
  private Map showPrivilegesHeader = new MapWrapper() {

    @Override
    public Boolean get(Object key) {
      Integer theInt = GrouperUtil.intObjectValue(key, false);
      int repeatAfterRows = GrouperUiConfig.retrieveConfig().propertyValueInt("simpleAttributeUpdate.repeatPrivilegeHeaderAfterRows", 20);

      if (theInt % repeatAfterRows == 0) {
        return true;
      }
      return false;
      
    }
    
  };
  
  /**
   * if we should show the privilege header
   * @return if we should show the privilege header
   */
  public Map getShowPrivilegeHeader() {
    
    return this.showPrivilegesHeader;
    
  }

  /** if optin should be checked on edit jsp */
  private boolean allowAllOptin;
  
  /** if optout should be checked on edit jsp */
  private boolean allowAllOptout;
  
  /** if read should be checked on edit jsp */
  private boolean allowAllRead;
  
  /** if view should be checked on edit jsp */
  private boolean allowAllView;
  
  /** if admin should be checked on edit jsp */
  private boolean allowAllAdmin;
  
  /** if update should be checked on edit jsp */
  private boolean allowAllUpdate;

  /** if attrDefAttrRead should be checked on edit jsp */
  private boolean allowAllAttrDefAttrRead;
  
  /** if attrDefAttrUpdate should be checked on edit jsp */
  private boolean allowAllAttrDefAttrUpdate;
  
  /**
   * directed graph nodes from
   */
  private List actionGraphNodesFrom;

  /**
   * directed graph nodes to
   */
  private List actionGraphNodesTo;

  /**
   * starting points in graph
   */
  private List actionGraphStartingPoints;
  
  /**
   * if optin should be checked on edit jsp
   * @return the editAttributeDefOptin
   */
  public boolean isAllowAllOptin() {
    return this.allowAllOptin;
  }
  
  /**
   * if optin should be checked on edit jsp
   * @param editAttributeDefOptin1 the editAttributeDefOptin to set
   */
  public void setAllowAllOptin(boolean editAttributeDefOptin1) {
    this.allowAllOptin = editAttributeDefOptin1;
  }
  
  /**
   * if attrDefAttrRead should be checked on edit jsp
   * @return the editAttributeDefAttrRead
   */
  public boolean isAllowAllAttrDefAttrRead() {
    return this.allowAllAttrDefAttrRead;
  }
  
  /**
   * if attrDefAttrRead should be checked on edit jsp
   * @param editAttributeDefAttrRead1 the editAttributeDefAttrRead to set
   */
  public void setAllowAllAttrDefAttrRead(boolean editAttributeDefAttrRead1) {
    this.allowAllAttrDefAttrRead = editAttributeDefAttrRead1;
  }
  
  /**
   * if attrDefAttrUpdate should be checked on edit jsp
   * @return the editAttributeDefAttrUpdate
   */
  public boolean isAllowAllAttrDefAttrUpdate() {
    return this.allowAllAttrDefAttrUpdate;
  }

  /**
   * if attrDefAttrUpdate should be checked on edit jsp
   * @param editAttributeDefAttrUpdate1 the editAttributeDefAttrUpdate to set
   */
  public void setAllowAllAttrDefAttrUpdate(boolean editAttributeDefAttrUpdate1) {
    this.allowAllAttrDefAttrUpdate = editAttributeDefAttrUpdate1;
  }
  
  
  /**
   * if optout should be checked on edit jsp
   * @return the editAttributeDefOptout
   */
  public boolean isAllowAllOptout() {
    return this.allowAllOptout;
  }

  
  /**
   * if optout should be checked on edit jsp
   * @param editAttributeDefOptout1 the editAttributeDefOptout to set
   */
  public void setAllowAllOptout(boolean editAttributeDefOptout1) {
    this.allowAllOptout = editAttributeDefOptout1;
  }

  
  /**
   * if read should be checked on edit jsp
   * @return the editAttributeDefRead
   */
  public boolean isAllowAllRead() {
    return this.allowAllRead;
  }

  
  /**
   * if read should be checked on edit jsp
   * @param editAttributeDefRead1 the editAttributeDefRead to set
   */
  public void setAllowAllRead(boolean editAttributeDefRead1) {
    this.allowAllRead = editAttributeDefRead1;
  }

  
  /**
   * if view should be checked on edit jsp
   * @return the editAttributeDefView
   */
  public boolean isAllowAllView() {
    return this.allowAllView;
  }

  
  /**
   * if view should be checked on edit jsp
   * @param editAttributeDefView1 the editAttributeDefView to set
   */
  public void setAllowAllView(boolean editAttributeDefView1) {
    this.allowAllView = editAttributeDefView1;
  }

  
  /**
   * if admin should be checked on edit jsp
   * @return the editAttributeDefAdmin
   */
  public boolean isAllowAllAdmin() {
    return this.allowAllAdmin;
  }

  
  /**
   * if admin should be checked on edit jsp
   * @param editAttributeDefAdmin1 the editAttributeDefAdmin to set
   */
  public void setAllowAllAdmin(boolean editAttributeDefAdmin1) {
    this.allowAllAdmin = editAttributeDefAdmin1;
  }

  
  /**
   * if update should be checked on edit jsp
   * @return the editAttributeDefUpdate
   */
  public boolean isAllowAllUpdate() {
    return this.allowAllUpdate;
  }

  
  /**
   * if update should be checked on edit jsp
   * @param editAttributeDefUpdate1 the editAttributeDefUpdate to set
   */
  public void setAllowAllUpdate(boolean editAttributeDefUpdate1) {
    this.allowAllUpdate = editAttributeDefUpdate1;
  }

  /**
   * gui attribute assign e.g. for edit screen
   * @return gui attribute assign
   */
  public GuiAttributeAssign getGuiAttributeAssign() {
    return this.guiAttributeAssign;
  }

  /**
   * gui attribute assignment e.g. for edit screen
   * @param guiAttributeAssign1
   */
  public void setGuiAttributeAssign(GuiAttributeAssign guiAttributeAssign1) {
    this.guiAttributeAssign = guiAttributeAssign1;
  }

  /**
   * directed graph nodes from
   * @return directed graph nodes from
   */
  public List getActionGraphNodesFrom() {
    return this.actionGraphNodesFrom;
  }

  /**
   * directed graph nodes to
   * @return directed graph nodes to
   */
  public List getActionGraphNodesTo() {
    return this.actionGraphNodesTo;
  }

  /**
   * starting points in graph
   * @return starting points in graph
   */
  public List getActionGraphStartingPoints() {
    return this.actionGraphStartingPoints;
  }

  /**
   * directed graph nodes from
   * @param attributeNameGraphNodesFrom1
   */
  public void setActionGraphNodesFrom(List attributeNameGraphNodesFrom1) {
    this.actionGraphNodesFrom = attributeNameGraphNodesFrom1;
  }

  /**
   * directed graph nodes to
   * @param attributeNameGraphNodesTo1
   */
  public void setActionGraphNodesTo(List attributeNameGraphNodesTo1) {
    this.actionGraphNodesTo = attributeNameGraphNodesTo1;
  }

  /**
   * starting points in graph
   * @param startingPoints1
   */
  public void setActionGraphStartingPoints(List startingPoints1) {
    this.actionGraphStartingPoints = startingPoints1;
  }
  


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy