/**
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
/**
 * Autogenerated by Thrift Compiler (0.9.3)
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */
package org.apache.airavata.sharing.registry.service.cpi;

import org.apache.thrift.scheme.IScheme;
import org.apache.thrift.scheme.SchemeFactory;
import org.apache.thrift.scheme.StandardScheme;

import org.apache.thrift.scheme.TupleScheme;
import org.apache.thrift.protocol.TTupleProtocol;
import org.apache.thrift.protocol.TProtocolException;
import org.apache.thrift.EncodingUtils;
import org.apache.thrift.TException;
import org.apache.thrift.async.AsyncMethodCallback;
import org.apache.thrift.server.AbstractNonblockingServer.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.EnumMap;
import java.util.Set;
import java.util.HashSet;
import java.util.EnumSet;
import java.util.Collections;
import java.util.BitSet;
import java.nio.ByteBuffer;
import java.util.Arrays;
import javax.annotation.Generated;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.3)")
public class SharingRegistryService {

  public interface Iface {

    /**
     * <p>API method to create a new domain</p>
     * 
     * @param domain
     */
    public String createDomain(org.apache.airavata.sharing.registry.models.Domain domain) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException;

    /**
     * <p>API method to update a domain</p>
     * 
     * @param domain
     */
    public boolean updateDomain(org.apache.airavata.sharing.registry.models.Domain domain) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to check Domain Exists</p>
     * 
     * @param domainId
     */
    public boolean isDomainExists(String domainId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to delete domain</p>
     * 
     * @param domainId
     */
    public boolean deleteDomain(String domainId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to retrieve a domain</p>
     * 
     * @param domainId
     */
    public org.apache.airavata.sharing.registry.models.Domain getDomain(String domainId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get all domain.</p>
     * 
     * @param offset
     * @param limit
     */
    public List<org.apache.airavata.sharing.registry.models.Domain> getDomains(int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to register a user in the system</p>
     * 
     * @param user
     */
    public String createUser(org.apache.airavata.sharing.registry.models.User user) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException;

    /**
     * <p>API method to update existing user</p>
     * 
     * @param user
     */
    public boolean updatedUser(org.apache.airavata.sharing.registry.models.User user) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to check User Exists</p>
     * 
     * @param domainId
     * @param userId
     */
    public boolean isUserExists(String domainId, String userId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to delete user</p>
     * 
     * @param domainId
     * @param userId
     */
    public boolean deleteUser(String domainId, String userId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get a user</p>
     * 
     * @param domainId
     * @param userId
     */
    public org.apache.airavata.sharing.registry.models.User getUser(String domainId, String userId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get a list of users in a specific domain.</p>
     * <li>domainId : Domain id</li>
     * <li>offset : Starting result number</li>
     * <li>limit : Number of max results to be sent</li>
     * 
     * @param domainId
     * @param offset
     * @param limit
     */
    public List<org.apache.airavata.sharing.registry.models.User> getUsers(String domainId, int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to create a new group</p>
     * 
     * @param group
     */
    public String createGroup(org.apache.airavata.sharing.registry.models.UserGroup group) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to update a group</p>
     * 
     * @param group
     */
    public boolean updateGroup(org.apache.airavata.sharing.registry.models.UserGroup group) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to check Group Exists</p>
     * 
     * @param domainId
     * @param groupId
     */
    public boolean isGroupExists(String domainId, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to delete a group</p>
     * 
     * @param domainId
     * @param groupId
     */
    public boolean deleteGroup(String domainId, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get a group</p>
     * 
     * @param domainId
     * @param groupId
     */
    public org.apache.airavata.sharing.registry.models.UserGroup getGroup(String domainId, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get groups in a domainId.</p>
     * 
     * @param domainId
     * @param offset
     * @param limit
     */
    public List<org.apache.airavata.sharing.registry.models.UserGroup> getGroups(String domainId, int offset, int limit) throws org.apache.thrift.TException;

    /**
     * <p>API method to add list of users to a group</p>
     * 
     * @param domainId
     * @param userIds
     * @param groupId
     */
    public boolean addUsersToGroup(String domainId, List<String> userIds, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to remove users from a group</p>
     * 
     * @param domainId
     * @param userIds
     * @param groupId
     */
    public boolean removeUsersFromGroup(String domainId, List<String> userIds, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get list of child users in a group. Only the direct members will be returned.</p>
     * 
     * @param domainId
     * @param groupId
     * @param offset
     * @param limit
     */
    public List<org.apache.airavata.sharing.registry.models.User> getGroupMembersOfTypeUser(String domainId, String groupId, int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get list of child groups in a group. Only the direct members will be returned.</p>
     * 
     * @param domainId
     * @param groupId
     * @param offset
     * @param limit
     */
    public List<org.apache.airavata.sharing.registry.models.UserGroup> getGroupMembersOfTypeGroup(String domainId, String groupId, int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to add a child group to a parent group.</p>
     * 
     * @param domainId
     * @param childIds
     * @param groupId
     */
    public boolean addChildGroupsToParentGroup(String domainId, List<String> childIds, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to remove a child group from parent group.</p>
     * 
     * @param domainId
     * @param childId
     * @param groupId
     */
    public boolean removeChildGroupFromParentGroup(String domainId, String childId, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    public List<org.apache.airavata.sharing.registry.models.UserGroup> getAllMemberGroupsForUser(String domainId, String userId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to create a new entity type</p>
     * 
     * @param entityType
     */
    public String createEntityType(org.apache.airavata.sharing.registry.models.EntityType entityType) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException;

    /**
     * <p>API method to update entity type</p>
     * 
     * @param entityType
     */
    public boolean updateEntityType(org.apache.airavata.sharing.registry.models.EntityType entityType) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to check EntityType Exists</p>
     * 
     * @param domainId
     * @param entityTypeId
     */
    public boolean isEntityTypeExists(String domainId, String entityTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to delete entity type</p>
     * 
     * @param domainId
     * @param entityTypeId
     */
    public boolean deleteEntityType(String domainId, String entityTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get an entity type</p>
     * 
     * @param domainId
     * @param entityTypeId
     */
    public org.apache.airavata.sharing.registry.models.EntityType getEntityType(String domainId, String entityTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get entity types in a domainId.</p>
     * 
     * @param domainId
     * @param offset
     * @param limit
     */
    public List<org.apache.airavata.sharing.registry.models.EntityType> getEntityTypes(String domainId, int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to register new entity</p>
     * 
     * @param entity
     */
    public String createEntity(org.apache.airavata.sharing.registry.models.Entity entity) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to update entity</p>
     * 
     * @param entity
     */
    public boolean updateEntity(org.apache.airavata.sharing.registry.models.Entity entity) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to check Entity Exists</p>
     * 
     * @param domainId
     * @param entityId
     */
    public boolean isEntityExists(String domainId, String entityId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to delete entity</p>
     * 
     * @param domainId
     * @param entityId
     */
    public boolean deleteEntity(String domainId, String entityId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get entity</p>
     * 
     * @param domainId
     * @param entityId
     */
    public org.apache.airavata.sharing.registry.models.Entity getEntity(String domainId, String entityId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to search entities</p>
     * 
     * @param domainId
     * @param userId
     * @param filters
     * @param offset
     * @param limit
     */
    public List<org.apache.airavata.sharing.registry.models.Entity> searchEntities(String domainId, String userId, List<org.apache.airavata.sharing.registry.models.SearchCriteria> filters, int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get a list of shared users given the entity id</p>
     * 
     * @param domainId
     * @param entityId
     * @param permissionTypeId
     */
    public List<org.apache.airavata.sharing.registry.models.User> getListOfSharedUsers(String domainId, String entityId, String permissionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get a list of shared groups given the entity id</p>
     * 
     * @param domainId
     * @param entityId
     * @param permissionTypeId
     */
    public List<org.apache.airavata.sharing.registry.models.UserGroup> getListOfSharedGroups(String domainId, String entityId, String permissionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to create permission type</p>
     * 
     * @param permissionType
     */
    public String createPermissionType(org.apache.airavata.sharing.registry.models.PermissionType permissionType) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException;

    /**
     * <p>API method to update permission type</p>
     * 
     * @param permissionType
     */
    public boolean updatePermissionType(org.apache.airavata.sharing.registry.models.PermissionType permissionType) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to check Permission Exists</p>
     * 
     * @param dimainId
     * @param permissionId
     */
    public boolean isPermissionExists(String dimainId, String permissionId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to delete permission type</p>
     * 
     * @param domainId
     * @param permissionTypeId
     */
    public boolean deletePermissionType(String domainId, String permissionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get permission type</p>
     * 
     * @param domainId
     * @param permissionTypeId
     */
    public org.apache.airavata.sharing.registry.models.PermissionType getPermissionType(String domainId, String permissionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to get list of permission types in a given domainId.</p>
     * 
     * @param domainId
     * @param offset
     * @param limit
     */
    public List<org.apache.airavata.sharing.registry.models.PermissionType> getPermissionTypes(String domainId, int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to share an entity with users</p>
     * 
     * @param domainId
     * @param entityId
     * @param userList
     * @param perssionTypeId
     * @param cascadePermission
     */
    public boolean shareEntityWithUsers(String domainId, String entityId, List<String> userList, String perssionTypeId, boolean cascadePermission) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to revoke sharing from a list of users</p>
     * 
     * @param domainId
     * @param entityId
     * @param userList
     * @param perssionTypeId
     */
    public boolean revokeEntitySharingFromUsers(String domainId, String entityId, List<String> userList, String perssionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to share an entity with list of groups</p>
     * 
     * @param domainId
     * @param entityId
     * @param groupList
     * @param perssionTypeId
     * @param cascadePermission
     */
    public boolean shareEntityWithGroups(String domainId, String entityId, List<String> groupList, String perssionTypeId, boolean cascadePermission) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to revoke sharing from list of users</p>
     * 
     * @param domainId
     * @param entityId
     * @param groupList
     * @param perssionTypeId
     */
    public boolean revokeEntitySharingFromGroups(String domainId, String entityId, List<String> groupList, String perssionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

    /**
     * <p>API method to check whether a user has access to a specific entity</p>
     * 
     * @param domainId
     * @param userId
     * @param entityId
     * @param permissionTypeId
     */
    public boolean userHasAccess(String domainId, String userId, String entityId, String permissionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException;

  }

  public interface AsyncIface {

    public void createDomain(org.apache.airavata.sharing.registry.models.Domain domain, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void updateDomain(org.apache.airavata.sharing.registry.models.Domain domain, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void isDomainExists(String domainId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void deleteDomain(String domainId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getDomain(String domainId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getDomains(int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void createUser(org.apache.airavata.sharing.registry.models.User user, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void updatedUser(org.apache.airavata.sharing.registry.models.User user, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void isUserExists(String domainId, String userId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void deleteUser(String domainId, String userId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getUser(String domainId, String userId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getUsers(String domainId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void createGroup(org.apache.airavata.sharing.registry.models.UserGroup group, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void updateGroup(org.apache.airavata.sharing.registry.models.UserGroup group, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void isGroupExists(String domainId, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void deleteGroup(String domainId, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getGroup(String domainId, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getGroups(String domainId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void addUsersToGroup(String domainId, List<String> userIds, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void removeUsersFromGroup(String domainId, List<String> userIds, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getGroupMembersOfTypeUser(String domainId, String groupId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getGroupMembersOfTypeGroup(String domainId, String groupId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void addChildGroupsToParentGroup(String domainId, List<String> childIds, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void removeChildGroupFromParentGroup(String domainId, String childId, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getAllMemberGroupsForUser(String domainId, String userId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void createEntityType(org.apache.airavata.sharing.registry.models.EntityType entityType, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void updateEntityType(org.apache.airavata.sharing.registry.models.EntityType entityType, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void isEntityTypeExists(String domainId, String entityTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void deleteEntityType(String domainId, String entityTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getEntityType(String domainId, String entityTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getEntityTypes(String domainId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void createEntity(org.apache.airavata.sharing.registry.models.Entity entity, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void updateEntity(org.apache.airavata.sharing.registry.models.Entity entity, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void isEntityExists(String domainId, String entityId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void deleteEntity(String domainId, String entityId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getEntity(String domainId, String entityId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void searchEntities(String domainId, String userId, List<org.apache.airavata.sharing.registry.models.SearchCriteria> filters, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getListOfSharedUsers(String domainId, String entityId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getListOfSharedGroups(String domainId, String entityId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void createPermissionType(org.apache.airavata.sharing.registry.models.PermissionType permissionType, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void updatePermissionType(org.apache.airavata.sharing.registry.models.PermissionType permissionType, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void isPermissionExists(String dimainId, String permissionId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void deletePermissionType(String domainId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getPermissionType(String domainId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void getPermissionTypes(String domainId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void shareEntityWithUsers(String domainId, String entityId, List<String> userList, String perssionTypeId, boolean cascadePermission, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void revokeEntitySharingFromUsers(String domainId, String entityId, List<String> userList, String perssionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void shareEntityWithGroups(String domainId, String entityId, List<String> groupList, String perssionTypeId, boolean cascadePermission, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void revokeEntitySharingFromGroups(String domainId, String entityId, List<String> groupList, String perssionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

    public void userHasAccess(String domainId, String userId, String entityId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;

  }

  public static class Client extends org.apache.thrift.TServiceClient implements Iface {
    public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
      public Factory() {}
      public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
        return new Client(prot);
      }
      public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
        return new Client(iprot, oprot);
      }
    }

    public Client(org.apache.thrift.protocol.TProtocol prot)
    {
      super(prot, prot);
    }

    public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
      super(iprot, oprot);
    }

    public String createDomain(org.apache.airavata.sharing.registry.models.Domain domain) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException
    {
      send_createDomain(domain);
      return recv_createDomain();
    }

    public void send_createDomain(org.apache.airavata.sharing.registry.models.Domain domain) throws org.apache.thrift.TException
    {
      createDomain_args args = new createDomain_args();
      args.setDomain(domain);
      sendBase("createDomain", args);
    }

    public String recv_createDomain() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException
    {
      createDomain_result result = new createDomain_result();
      receiveBase(result, "createDomain");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      if (result.dee != null) {
        throw result.dee;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "createDomain failed: unknown result");
    }

    public boolean updateDomain(org.apache.airavata.sharing.registry.models.Domain domain) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_updateDomain(domain);
      return recv_updateDomain();
    }

    public void send_updateDomain(org.apache.airavata.sharing.registry.models.Domain domain) throws org.apache.thrift.TException
    {
      updateDomain_args args = new updateDomain_args();
      args.setDomain(domain);
      sendBase("updateDomain", args);
    }

    public boolean recv_updateDomain() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      updateDomain_result result = new updateDomain_result();
      receiveBase(result, "updateDomain");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "updateDomain failed: unknown result");
    }

    public boolean isDomainExists(String domainId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_isDomainExists(domainId);
      return recv_isDomainExists();
    }

    public void send_isDomainExists(String domainId) throws org.apache.thrift.TException
    {
      isDomainExists_args args = new isDomainExists_args();
      args.setDomainId(domainId);
      sendBase("isDomainExists", args);
    }

    public boolean recv_isDomainExists() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      isDomainExists_result result = new isDomainExists_result();
      receiveBase(result, "isDomainExists");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "isDomainExists failed: unknown result");
    }

    public boolean deleteDomain(String domainId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_deleteDomain(domainId);
      return recv_deleteDomain();
    }

    public void send_deleteDomain(String domainId) throws org.apache.thrift.TException
    {
      deleteDomain_args args = new deleteDomain_args();
      args.setDomainId(domainId);
      sendBase("deleteDomain", args);
    }

    public boolean recv_deleteDomain() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      deleteDomain_result result = new deleteDomain_result();
      receiveBase(result, "deleteDomain");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "deleteDomain failed: unknown result");
    }

    public org.apache.airavata.sharing.registry.models.Domain getDomain(String domainId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getDomain(domainId);
      return recv_getDomain();
    }

    public void send_getDomain(String domainId) throws org.apache.thrift.TException
    {
      getDomain_args args = new getDomain_args();
      args.setDomainId(domainId);
      sendBase("getDomain", args);
    }

    public org.apache.airavata.sharing.registry.models.Domain recv_getDomain() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getDomain_result result = new getDomain_result();
      receiveBase(result, "getDomain");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getDomain failed: unknown result");
    }

    public List<org.apache.airavata.sharing.registry.models.Domain> getDomains(int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getDomains(offset, limit);
      return recv_getDomains();
    }

    public void send_getDomains(int offset, int limit) throws org.apache.thrift.TException
    {
      getDomains_args args = new getDomains_args();
      args.setOffset(offset);
      args.setLimit(limit);
      sendBase("getDomains", args);
    }

    public List<org.apache.airavata.sharing.registry.models.Domain> recv_getDomains() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getDomains_result result = new getDomains_result();
      receiveBase(result, "getDomains");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getDomains failed: unknown result");
    }

    public String createUser(org.apache.airavata.sharing.registry.models.User user) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException
    {
      send_createUser(user);
      return recv_createUser();
    }

    public void send_createUser(org.apache.airavata.sharing.registry.models.User user) throws org.apache.thrift.TException
    {
      createUser_args args = new createUser_args();
      args.setUser(user);
      sendBase("createUser", args);
    }

    public String recv_createUser() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException
    {
      createUser_result result = new createUser_result();
      receiveBase(result, "createUser");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      if (result.dee != null) {
        throw result.dee;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "createUser failed: unknown result");
    }

    public boolean updatedUser(org.apache.airavata.sharing.registry.models.User user) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_updatedUser(user);
      return recv_updatedUser();
    }

    public void send_updatedUser(org.apache.airavata.sharing.registry.models.User user) throws org.apache.thrift.TException
    {
      updatedUser_args args = new updatedUser_args();
      args.setUser(user);
      sendBase("updatedUser", args);
    }

    public boolean recv_updatedUser() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      updatedUser_result result = new updatedUser_result();
      receiveBase(result, "updatedUser");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "updatedUser failed: unknown result");
    }

    public boolean isUserExists(String domainId, String userId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_isUserExists(domainId, userId);
      return recv_isUserExists();
    }

    public void send_isUserExists(String domainId, String userId) throws org.apache.thrift.TException
    {
      isUserExists_args args = new isUserExists_args();
      args.setDomainId(domainId);
      args.setUserId(userId);
      sendBase("isUserExists", args);
    }

    public boolean recv_isUserExists() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      isUserExists_result result = new isUserExists_result();
      receiveBase(result, "isUserExists");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "isUserExists failed: unknown result");
    }

    public boolean deleteUser(String domainId, String userId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_deleteUser(domainId, userId);
      return recv_deleteUser();
    }

    public void send_deleteUser(String domainId, String userId) throws org.apache.thrift.TException
    {
      deleteUser_args args = new deleteUser_args();
      args.setDomainId(domainId);
      args.setUserId(userId);
      sendBase("deleteUser", args);
    }

    public boolean recv_deleteUser() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      deleteUser_result result = new deleteUser_result();
      receiveBase(result, "deleteUser");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "deleteUser failed: unknown result");
    }

    public org.apache.airavata.sharing.registry.models.User getUser(String domainId, String userId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getUser(domainId, userId);
      return recv_getUser();
    }

    public void send_getUser(String domainId, String userId) throws org.apache.thrift.TException
    {
      getUser_args args = new getUser_args();
      args.setDomainId(domainId);
      args.setUserId(userId);
      sendBase("getUser", args);
    }

    public org.apache.airavata.sharing.registry.models.User recv_getUser() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getUser_result result = new getUser_result();
      receiveBase(result, "getUser");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getUser failed: unknown result");
    }

    public List<org.apache.airavata.sharing.registry.models.User> getUsers(String domainId, int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getUsers(domainId, offset, limit);
      return recv_getUsers();
    }

    public void send_getUsers(String domainId, int offset, int limit) throws org.apache.thrift.TException
    {
      getUsers_args args = new getUsers_args();
      args.setDomainId(domainId);
      args.setOffset(offset);
      args.setLimit(limit);
      sendBase("getUsers", args);
    }

    public List<org.apache.airavata.sharing.registry.models.User> recv_getUsers() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getUsers_result result = new getUsers_result();
      receiveBase(result, "getUsers");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getUsers failed: unknown result");
    }

    public String createGroup(org.apache.airavata.sharing.registry.models.UserGroup group) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_createGroup(group);
      return recv_createGroup();
    }

    public void send_createGroup(org.apache.airavata.sharing.registry.models.UserGroup group) throws org.apache.thrift.TException
    {
      createGroup_args args = new createGroup_args();
      args.setGroup(group);
      sendBase("createGroup", args);
    }

    public String recv_createGroup() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      createGroup_result result = new createGroup_result();
      receiveBase(result, "createGroup");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "createGroup failed: unknown result");
    }

    public boolean updateGroup(org.apache.airavata.sharing.registry.models.UserGroup group) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_updateGroup(group);
      return recv_updateGroup();
    }

    public void send_updateGroup(org.apache.airavata.sharing.registry.models.UserGroup group) throws org.apache.thrift.TException
    {
      updateGroup_args args = new updateGroup_args();
      args.setGroup(group);
      sendBase("updateGroup", args);
    }

    public boolean recv_updateGroup() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      updateGroup_result result = new updateGroup_result();
      receiveBase(result, "updateGroup");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "updateGroup failed: unknown result");
    }

    public boolean isGroupExists(String domainId, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_isGroupExists(domainId, groupId);
      return recv_isGroupExists();
    }

    public void send_isGroupExists(String domainId, String groupId) throws org.apache.thrift.TException
    {
      isGroupExists_args args = new isGroupExists_args();
      args.setDomainId(domainId);
      args.setGroupId(groupId);
      sendBase("isGroupExists", args);
    }

    public boolean recv_isGroupExists() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      isGroupExists_result result = new isGroupExists_result();
      receiveBase(result, "isGroupExists");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "isGroupExists failed: unknown result");
    }

    public boolean deleteGroup(String domainId, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_deleteGroup(domainId, groupId);
      return recv_deleteGroup();
    }

    public void send_deleteGroup(String domainId, String groupId) throws org.apache.thrift.TException
    {
      deleteGroup_args args = new deleteGroup_args();
      args.setDomainId(domainId);
      args.setGroupId(groupId);
      sendBase("deleteGroup", args);
    }

    public boolean recv_deleteGroup() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      deleteGroup_result result = new deleteGroup_result();
      receiveBase(result, "deleteGroup");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "deleteGroup failed: unknown result");
    }

    public org.apache.airavata.sharing.registry.models.UserGroup getGroup(String domainId, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getGroup(domainId, groupId);
      return recv_getGroup();
    }

    public void send_getGroup(String domainId, String groupId) throws org.apache.thrift.TException
    {
      getGroup_args args = new getGroup_args();
      args.setDomainId(domainId);
      args.setGroupId(groupId);
      sendBase("getGroup", args);
    }

    public org.apache.airavata.sharing.registry.models.UserGroup recv_getGroup() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getGroup_result result = new getGroup_result();
      receiveBase(result, "getGroup");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getGroup failed: unknown result");
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> getGroups(String domainId, int offset, int limit) throws org.apache.thrift.TException
    {
      send_getGroups(domainId, offset, limit);
      return recv_getGroups();
    }

    public void send_getGroups(String domainId, int offset, int limit) throws org.apache.thrift.TException
    {
      getGroups_args args = new getGroups_args();
      args.setDomainId(domainId);
      args.setOffset(offset);
      args.setLimit(limit);
      sendBase("getGroups", args);
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> recv_getGroups() throws org.apache.thrift.TException
    {
      getGroups_result result = new getGroups_result();
      receiveBase(result, "getGroups");
      if (result.isSetSuccess()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getGroups failed: unknown result");
    }

    public boolean addUsersToGroup(String domainId, List<String> userIds, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_addUsersToGroup(domainId, userIds, groupId);
      return recv_addUsersToGroup();
    }

    public void send_addUsersToGroup(String domainId, List<String> userIds, String groupId) throws org.apache.thrift.TException
    {
      addUsersToGroup_args args = new addUsersToGroup_args();
      args.setDomainId(domainId);
      args.setUserIds(userIds);
      args.setGroupId(groupId);
      sendBase("addUsersToGroup", args);
    }

    public boolean recv_addUsersToGroup() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      addUsersToGroup_result result = new addUsersToGroup_result();
      receiveBase(result, "addUsersToGroup");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "addUsersToGroup failed: unknown result");
    }

    public boolean removeUsersFromGroup(String domainId, List<String> userIds, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_removeUsersFromGroup(domainId, userIds, groupId);
      return recv_removeUsersFromGroup();
    }

    public void send_removeUsersFromGroup(String domainId, List<String> userIds, String groupId) throws org.apache.thrift.TException
    {
      removeUsersFromGroup_args args = new removeUsersFromGroup_args();
      args.setDomainId(domainId);
      args.setUserIds(userIds);
      args.setGroupId(groupId);
      sendBase("removeUsersFromGroup", args);
    }

    public boolean recv_removeUsersFromGroup() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      removeUsersFromGroup_result result = new removeUsersFromGroup_result();
      receiveBase(result, "removeUsersFromGroup");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "removeUsersFromGroup failed: unknown result");
    }

    public List<org.apache.airavata.sharing.registry.models.User> getGroupMembersOfTypeUser(String domainId, String groupId, int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getGroupMembersOfTypeUser(domainId, groupId, offset, limit);
      return recv_getGroupMembersOfTypeUser();
    }

    public void send_getGroupMembersOfTypeUser(String domainId, String groupId, int offset, int limit) throws org.apache.thrift.TException
    {
      getGroupMembersOfTypeUser_args args = new getGroupMembersOfTypeUser_args();
      args.setDomainId(domainId);
      args.setGroupId(groupId);
      args.setOffset(offset);
      args.setLimit(limit);
      sendBase("getGroupMembersOfTypeUser", args);
    }

    public List<org.apache.airavata.sharing.registry.models.User> recv_getGroupMembersOfTypeUser() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getGroupMembersOfTypeUser_result result = new getGroupMembersOfTypeUser_result();
      receiveBase(result, "getGroupMembersOfTypeUser");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getGroupMembersOfTypeUser failed: unknown result");
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> getGroupMembersOfTypeGroup(String domainId, String groupId, int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getGroupMembersOfTypeGroup(domainId, groupId, offset, limit);
      return recv_getGroupMembersOfTypeGroup();
    }

    public void send_getGroupMembersOfTypeGroup(String domainId, String groupId, int offset, int limit) throws org.apache.thrift.TException
    {
      getGroupMembersOfTypeGroup_args args = new getGroupMembersOfTypeGroup_args();
      args.setDomainId(domainId);
      args.setGroupId(groupId);
      args.setOffset(offset);
      args.setLimit(limit);
      sendBase("getGroupMembersOfTypeGroup", args);
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> recv_getGroupMembersOfTypeGroup() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getGroupMembersOfTypeGroup_result result = new getGroupMembersOfTypeGroup_result();
      receiveBase(result, "getGroupMembersOfTypeGroup");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getGroupMembersOfTypeGroup failed: unknown result");
    }

    public boolean addChildGroupsToParentGroup(String domainId, List<String> childIds, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_addChildGroupsToParentGroup(domainId, childIds, groupId);
      return recv_addChildGroupsToParentGroup();
    }

    public void send_addChildGroupsToParentGroup(String domainId, List<String> childIds, String groupId) throws org.apache.thrift.TException
    {
      addChildGroupsToParentGroup_args args = new addChildGroupsToParentGroup_args();
      args.setDomainId(domainId);
      args.setChildIds(childIds);
      args.setGroupId(groupId);
      sendBase("addChildGroupsToParentGroup", args);
    }

    public boolean recv_addChildGroupsToParentGroup() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      addChildGroupsToParentGroup_result result = new addChildGroupsToParentGroup_result();
      receiveBase(result, "addChildGroupsToParentGroup");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "addChildGroupsToParentGroup failed: unknown result");
    }

    public boolean removeChildGroupFromParentGroup(String domainId, String childId, String groupId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_removeChildGroupFromParentGroup(domainId, childId, groupId);
      return recv_removeChildGroupFromParentGroup();
    }

    public void send_removeChildGroupFromParentGroup(String domainId, String childId, String groupId) throws org.apache.thrift.TException
    {
      removeChildGroupFromParentGroup_args args = new removeChildGroupFromParentGroup_args();
      args.setDomainId(domainId);
      args.setChildId(childId);
      args.setGroupId(groupId);
      sendBase("removeChildGroupFromParentGroup", args);
    }

    public boolean recv_removeChildGroupFromParentGroup() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      removeChildGroupFromParentGroup_result result = new removeChildGroupFromParentGroup_result();
      receiveBase(result, "removeChildGroupFromParentGroup");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "removeChildGroupFromParentGroup failed: unknown result");
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> getAllMemberGroupsForUser(String domainId, String userId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getAllMemberGroupsForUser(domainId, userId);
      return recv_getAllMemberGroupsForUser();
    }

    public void send_getAllMemberGroupsForUser(String domainId, String userId) throws org.apache.thrift.TException
    {
      getAllMemberGroupsForUser_args args = new getAllMemberGroupsForUser_args();
      args.setDomainId(domainId);
      args.setUserId(userId);
      sendBase("getAllMemberGroupsForUser", args);
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> recv_getAllMemberGroupsForUser() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getAllMemberGroupsForUser_result result = new getAllMemberGroupsForUser_result();
      receiveBase(result, "getAllMemberGroupsForUser");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getAllMemberGroupsForUser failed: unknown result");
    }

    public String createEntityType(org.apache.airavata.sharing.registry.models.EntityType entityType) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException
    {
      send_createEntityType(entityType);
      return recv_createEntityType();
    }

    public void send_createEntityType(org.apache.airavata.sharing.registry.models.EntityType entityType) throws org.apache.thrift.TException
    {
      createEntityType_args args = new createEntityType_args();
      args.setEntityType(entityType);
      sendBase("createEntityType", args);
    }

    public String recv_createEntityType() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException
    {
      createEntityType_result result = new createEntityType_result();
      receiveBase(result, "createEntityType");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      if (result.dee != null) {
        throw result.dee;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "createEntityType failed: unknown result");
    }

    public boolean updateEntityType(org.apache.airavata.sharing.registry.models.EntityType entityType) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_updateEntityType(entityType);
      return recv_updateEntityType();
    }

    public void send_updateEntityType(org.apache.airavata.sharing.registry.models.EntityType entityType) throws org.apache.thrift.TException
    {
      updateEntityType_args args = new updateEntityType_args();
      args.setEntityType(entityType);
      sendBase("updateEntityType", args);
    }

    public boolean recv_updateEntityType() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      updateEntityType_result result = new updateEntityType_result();
      receiveBase(result, "updateEntityType");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "updateEntityType failed: unknown result");
    }

    public boolean isEntityTypeExists(String domainId, String entityTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_isEntityTypeExists(domainId, entityTypeId);
      return recv_isEntityTypeExists();
    }

    public void send_isEntityTypeExists(String domainId, String entityTypeId) throws org.apache.thrift.TException
    {
      isEntityTypeExists_args args = new isEntityTypeExists_args();
      args.setDomainId(domainId);
      args.setEntityTypeId(entityTypeId);
      sendBase("isEntityTypeExists", args);
    }

    public boolean recv_isEntityTypeExists() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      isEntityTypeExists_result result = new isEntityTypeExists_result();
      receiveBase(result, "isEntityTypeExists");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "isEntityTypeExists failed: unknown result");
    }

    public boolean deleteEntityType(String domainId, String entityTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_deleteEntityType(domainId, entityTypeId);
      return recv_deleteEntityType();
    }

    public void send_deleteEntityType(String domainId, String entityTypeId) throws org.apache.thrift.TException
    {
      deleteEntityType_args args = new deleteEntityType_args();
      args.setDomainId(domainId);
      args.setEntityTypeId(entityTypeId);
      sendBase("deleteEntityType", args);
    }

    public boolean recv_deleteEntityType() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      deleteEntityType_result result = new deleteEntityType_result();
      receiveBase(result, "deleteEntityType");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "deleteEntityType failed: unknown result");
    }

    public org.apache.airavata.sharing.registry.models.EntityType getEntityType(String domainId, String entityTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getEntityType(domainId, entityTypeId);
      return recv_getEntityType();
    }

    public void send_getEntityType(String domainId, String entityTypeId) throws org.apache.thrift.TException
    {
      getEntityType_args args = new getEntityType_args();
      args.setDomainId(domainId);
      args.setEntityTypeId(entityTypeId);
      sendBase("getEntityType", args);
    }

    public org.apache.airavata.sharing.registry.models.EntityType recv_getEntityType() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getEntityType_result result = new getEntityType_result();
      receiveBase(result, "getEntityType");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getEntityType failed: unknown result");
    }

    public List<org.apache.airavata.sharing.registry.models.EntityType> getEntityTypes(String domainId, int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getEntityTypes(domainId, offset, limit);
      return recv_getEntityTypes();
    }

    public void send_getEntityTypes(String domainId, int offset, int limit) throws org.apache.thrift.TException
    {
      getEntityTypes_args args = new getEntityTypes_args();
      args.setDomainId(domainId);
      args.setOffset(offset);
      args.setLimit(limit);
      sendBase("getEntityTypes", args);
    }

    public List<org.apache.airavata.sharing.registry.models.EntityType> recv_getEntityTypes() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getEntityTypes_result result = new getEntityTypes_result();
      receiveBase(result, "getEntityTypes");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getEntityTypes failed: unknown result");
    }

    public String createEntity(org.apache.airavata.sharing.registry.models.Entity entity) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_createEntity(entity);
      return recv_createEntity();
    }

    public void send_createEntity(org.apache.airavata.sharing.registry.models.Entity entity) throws org.apache.thrift.TException
    {
      createEntity_args args = new createEntity_args();
      args.setEntity(entity);
      sendBase("createEntity", args);
    }

    public String recv_createEntity() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      createEntity_result result = new createEntity_result();
      receiveBase(result, "createEntity");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "createEntity failed: unknown result");
    }

    public boolean updateEntity(org.apache.airavata.sharing.registry.models.Entity entity) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_updateEntity(entity);
      return recv_updateEntity();
    }

    public void send_updateEntity(org.apache.airavata.sharing.registry.models.Entity entity) throws org.apache.thrift.TException
    {
      updateEntity_args args = new updateEntity_args();
      args.setEntity(entity);
      sendBase("updateEntity", args);
    }

    public boolean recv_updateEntity() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      updateEntity_result result = new updateEntity_result();
      receiveBase(result, "updateEntity");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "updateEntity failed: unknown result");
    }

    public boolean isEntityExists(String domainId, String entityId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_isEntityExists(domainId, entityId);
      return recv_isEntityExists();
    }

    public void send_isEntityExists(String domainId, String entityId) throws org.apache.thrift.TException
    {
      isEntityExists_args args = new isEntityExists_args();
      args.setDomainId(domainId);
      args.setEntityId(entityId);
      sendBase("isEntityExists", args);
    }

    public boolean recv_isEntityExists() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      isEntityExists_result result = new isEntityExists_result();
      receiveBase(result, "isEntityExists");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "isEntityExists failed: unknown result");
    }

    public boolean deleteEntity(String domainId, String entityId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_deleteEntity(domainId, entityId);
      return recv_deleteEntity();
    }

    public void send_deleteEntity(String domainId, String entityId) throws org.apache.thrift.TException
    {
      deleteEntity_args args = new deleteEntity_args();
      args.setDomainId(domainId);
      args.setEntityId(entityId);
      sendBase("deleteEntity", args);
    }

    public boolean recv_deleteEntity() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      deleteEntity_result result = new deleteEntity_result();
      receiveBase(result, "deleteEntity");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "deleteEntity failed: unknown result");
    }

    public org.apache.airavata.sharing.registry.models.Entity getEntity(String domainId, String entityId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getEntity(domainId, entityId);
      return recv_getEntity();
    }

    public void send_getEntity(String domainId, String entityId) throws org.apache.thrift.TException
    {
      getEntity_args args = new getEntity_args();
      args.setDomainId(domainId);
      args.setEntityId(entityId);
      sendBase("getEntity", args);
    }

    public org.apache.airavata.sharing.registry.models.Entity recv_getEntity() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getEntity_result result = new getEntity_result();
      receiveBase(result, "getEntity");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getEntity failed: unknown result");
    }

    public List<org.apache.airavata.sharing.registry.models.Entity> searchEntities(String domainId, String userId, List<org.apache.airavata.sharing.registry.models.SearchCriteria> filters, int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_searchEntities(domainId, userId, filters, offset, limit);
      return recv_searchEntities();
    }

    public void send_searchEntities(String domainId, String userId, List<org.apache.airavata.sharing.registry.models.SearchCriteria> filters, int offset, int limit) throws org.apache.thrift.TException
    {
      searchEntities_args args = new searchEntities_args();
      args.setDomainId(domainId);
      args.setUserId(userId);
      args.setFilters(filters);
      args.setOffset(offset);
      args.setLimit(limit);
      sendBase("searchEntities", args);
    }

    public List<org.apache.airavata.sharing.registry.models.Entity> recv_searchEntities() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      searchEntities_result result = new searchEntities_result();
      receiveBase(result, "searchEntities");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "searchEntities failed: unknown result");
    }

    public List<org.apache.airavata.sharing.registry.models.User> getListOfSharedUsers(String domainId, String entityId, String permissionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getListOfSharedUsers(domainId, entityId, permissionTypeId);
      return recv_getListOfSharedUsers();
    }

    public void send_getListOfSharedUsers(String domainId, String entityId, String permissionTypeId) throws org.apache.thrift.TException
    {
      getListOfSharedUsers_args args = new getListOfSharedUsers_args();
      args.setDomainId(domainId);
      args.setEntityId(entityId);
      args.setPermissionTypeId(permissionTypeId);
      sendBase("getListOfSharedUsers", args);
    }

    public List<org.apache.airavata.sharing.registry.models.User> recv_getListOfSharedUsers() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getListOfSharedUsers_result result = new getListOfSharedUsers_result();
      receiveBase(result, "getListOfSharedUsers");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getListOfSharedUsers failed: unknown result");
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> getListOfSharedGroups(String domainId, String entityId, String permissionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getListOfSharedGroups(domainId, entityId, permissionTypeId);
      return recv_getListOfSharedGroups();
    }

    public void send_getListOfSharedGroups(String domainId, String entityId, String permissionTypeId) throws org.apache.thrift.TException
    {
      getListOfSharedGroups_args args = new getListOfSharedGroups_args();
      args.setDomainId(domainId);
      args.setEntityId(entityId);
      args.setPermissionTypeId(permissionTypeId);
      sendBase("getListOfSharedGroups", args);
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> recv_getListOfSharedGroups() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getListOfSharedGroups_result result = new getListOfSharedGroups_result();
      receiveBase(result, "getListOfSharedGroups");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getListOfSharedGroups failed: unknown result");
    }

    public String createPermissionType(org.apache.airavata.sharing.registry.models.PermissionType permissionType) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException
    {
      send_createPermissionType(permissionType);
      return recv_createPermissionType();
    }

    public void send_createPermissionType(org.apache.airavata.sharing.registry.models.PermissionType permissionType) throws org.apache.thrift.TException
    {
      createPermissionType_args args = new createPermissionType_args();
      args.setPermissionType(permissionType);
      sendBase("createPermissionType", args);
    }

    public String recv_createPermissionType() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException
    {
      createPermissionType_result result = new createPermissionType_result();
      receiveBase(result, "createPermissionType");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      if (result.dee != null) {
        throw result.dee;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "createPermissionType failed: unknown result");
    }

    public boolean updatePermissionType(org.apache.airavata.sharing.registry.models.PermissionType permissionType) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_updatePermissionType(permissionType);
      return recv_updatePermissionType();
    }

    public void send_updatePermissionType(org.apache.airavata.sharing.registry.models.PermissionType permissionType) throws org.apache.thrift.TException
    {
      updatePermissionType_args args = new updatePermissionType_args();
      args.setPermissionType(permissionType);
      sendBase("updatePermissionType", args);
    }

    public boolean recv_updatePermissionType() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      updatePermissionType_result result = new updatePermissionType_result();
      receiveBase(result, "updatePermissionType");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "updatePermissionType failed: unknown result");
    }

    public boolean isPermissionExists(String dimainId, String permissionId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_isPermissionExists(dimainId, permissionId);
      return recv_isPermissionExists();
    }

    public void send_isPermissionExists(String dimainId, String permissionId) throws org.apache.thrift.TException
    {
      isPermissionExists_args args = new isPermissionExists_args();
      args.setDimainId(dimainId);
      args.setPermissionId(permissionId);
      sendBase("isPermissionExists", args);
    }

    public boolean recv_isPermissionExists() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      isPermissionExists_result result = new isPermissionExists_result();
      receiveBase(result, "isPermissionExists");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "isPermissionExists failed: unknown result");
    }

    public boolean deletePermissionType(String domainId, String permissionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_deletePermissionType(domainId, permissionTypeId);
      return recv_deletePermissionType();
    }

    public void send_deletePermissionType(String domainId, String permissionTypeId) throws org.apache.thrift.TException
    {
      deletePermissionType_args args = new deletePermissionType_args();
      args.setDomainId(domainId);
      args.setPermissionTypeId(permissionTypeId);
      sendBase("deletePermissionType", args);
    }

    public boolean recv_deletePermissionType() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      deletePermissionType_result result = new deletePermissionType_result();
      receiveBase(result, "deletePermissionType");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "deletePermissionType failed: unknown result");
    }

    public org.apache.airavata.sharing.registry.models.PermissionType getPermissionType(String domainId, String permissionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getPermissionType(domainId, permissionTypeId);
      return recv_getPermissionType();
    }

    public void send_getPermissionType(String domainId, String permissionTypeId) throws org.apache.thrift.TException
    {
      getPermissionType_args args = new getPermissionType_args();
      args.setDomainId(domainId);
      args.setPermissionTypeId(permissionTypeId);
      sendBase("getPermissionType", args);
    }

    public org.apache.airavata.sharing.registry.models.PermissionType recv_getPermissionType() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getPermissionType_result result = new getPermissionType_result();
      receiveBase(result, "getPermissionType");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getPermissionType failed: unknown result");
    }

    public List<org.apache.airavata.sharing.registry.models.PermissionType> getPermissionTypes(String domainId, int offset, int limit) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_getPermissionTypes(domainId, offset, limit);
      return recv_getPermissionTypes();
    }

    public void send_getPermissionTypes(String domainId, int offset, int limit) throws org.apache.thrift.TException
    {
      getPermissionTypes_args args = new getPermissionTypes_args();
      args.setDomainId(domainId);
      args.setOffset(offset);
      args.setLimit(limit);
      sendBase("getPermissionTypes", args);
    }

    public List<org.apache.airavata.sharing.registry.models.PermissionType> recv_getPermissionTypes() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      getPermissionTypes_result result = new getPermissionTypes_result();
      receiveBase(result, "getPermissionTypes");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getPermissionTypes failed: unknown result");
    }

    public boolean shareEntityWithUsers(String domainId, String entityId, List<String> userList, String perssionTypeId, boolean cascadePermission) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_shareEntityWithUsers(domainId, entityId, userList, perssionTypeId, cascadePermission);
      return recv_shareEntityWithUsers();
    }

    public void send_shareEntityWithUsers(String domainId, String entityId, List<String> userList, String perssionTypeId, boolean cascadePermission) throws org.apache.thrift.TException
    {
      shareEntityWithUsers_args args = new shareEntityWithUsers_args();
      args.setDomainId(domainId);
      args.setEntityId(entityId);
      args.setUserList(userList);
      args.setPerssionTypeId(perssionTypeId);
      args.setCascadePermission(cascadePermission);
      sendBase("shareEntityWithUsers", args);
    }

    public boolean recv_shareEntityWithUsers() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      shareEntityWithUsers_result result = new shareEntityWithUsers_result();
      receiveBase(result, "shareEntityWithUsers");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "shareEntityWithUsers failed: unknown result");
    }

    public boolean revokeEntitySharingFromUsers(String domainId, String entityId, List<String> userList, String perssionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_revokeEntitySharingFromUsers(domainId, entityId, userList, perssionTypeId);
      return recv_revokeEntitySharingFromUsers();
    }

    public void send_revokeEntitySharingFromUsers(String domainId, String entityId, List<String> userList, String perssionTypeId) throws org.apache.thrift.TException
    {
      revokeEntitySharingFromUsers_args args = new revokeEntitySharingFromUsers_args();
      args.setDomainId(domainId);
      args.setEntityId(entityId);
      args.setUserList(userList);
      args.setPerssionTypeId(perssionTypeId);
      sendBase("revokeEntitySharingFromUsers", args);
    }

    public boolean recv_revokeEntitySharingFromUsers() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      revokeEntitySharingFromUsers_result result = new revokeEntitySharingFromUsers_result();
      receiveBase(result, "revokeEntitySharingFromUsers");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "revokeEntitySharingFromUsers failed: unknown result");
    }

    public boolean shareEntityWithGroups(String domainId, String entityId, List<String> groupList, String perssionTypeId, boolean cascadePermission) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_shareEntityWithGroups(domainId, entityId, groupList, perssionTypeId, cascadePermission);
      return recv_shareEntityWithGroups();
    }

    public void send_shareEntityWithGroups(String domainId, String entityId, List<String> groupList, String perssionTypeId, boolean cascadePermission) throws org.apache.thrift.TException
    {
      shareEntityWithGroups_args args = new shareEntityWithGroups_args();
      args.setDomainId(domainId);
      args.setEntityId(entityId);
      args.setGroupList(groupList);
      args.setPerssionTypeId(perssionTypeId);
      args.setCascadePermission(cascadePermission);
      sendBase("shareEntityWithGroups", args);
    }

    public boolean recv_shareEntityWithGroups() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      shareEntityWithGroups_result result = new shareEntityWithGroups_result();
      receiveBase(result, "shareEntityWithGroups");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "shareEntityWithGroups failed: unknown result");
    }

    public boolean revokeEntitySharingFromGroups(String domainId, String entityId, List<String> groupList, String perssionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_revokeEntitySharingFromGroups(domainId, entityId, groupList, perssionTypeId);
      return recv_revokeEntitySharingFromGroups();
    }

    public void send_revokeEntitySharingFromGroups(String domainId, String entityId, List<String> groupList, String perssionTypeId) throws org.apache.thrift.TException
    {
      revokeEntitySharingFromGroups_args args = new revokeEntitySharingFromGroups_args();
      args.setDomainId(domainId);
      args.setEntityId(entityId);
      args.setGroupList(groupList);
      args.setPerssionTypeId(perssionTypeId);
      sendBase("revokeEntitySharingFromGroups", args);
    }

    public boolean recv_revokeEntitySharingFromGroups() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      revokeEntitySharingFromGroups_result result = new revokeEntitySharingFromGroups_result();
      receiveBase(result, "revokeEntitySharingFromGroups");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "revokeEntitySharingFromGroups failed: unknown result");
    }

    public boolean userHasAccess(String domainId, String userId, String entityId, String permissionTypeId) throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      send_userHasAccess(domainId, userId, entityId, permissionTypeId);
      return recv_userHasAccess();
    }

    public void send_userHasAccess(String domainId, String userId, String entityId, String permissionTypeId) throws org.apache.thrift.TException
    {
      userHasAccess_args args = new userHasAccess_args();
      args.setDomainId(domainId);
      args.setUserId(userId);
      args.setEntityId(entityId);
      args.setPermissionTypeId(permissionTypeId);
      sendBase("userHasAccess", args);
    }

    public boolean recv_userHasAccess() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException
    {
      userHasAccess_result result = new userHasAccess_result();
      receiveBase(result, "userHasAccess");
      if (result.isSetSuccess()) {
        return result.success;
      }
      if (result.sre != null) {
        throw result.sre;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "userHasAccess failed: unknown result");
    }

  }
  public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface {
    public static class Factory implements org.apache.thrift.async.TAsyncClientFactory<AsyncClient> {
      private org.apache.thrift.async.TAsyncClientManager clientManager;
      private org.apache.thrift.protocol.TProtocolFactory protocolFactory;
      public Factory(org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.protocol.TProtocolFactory protocolFactory) {
        this.clientManager = clientManager;
        this.protocolFactory = protocolFactory;
      }
      public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {
        return new AsyncClient(protocolFactory, clientManager, transport);
      }
    }

    public AsyncClient(org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.transport.TNonblockingTransport transport) {
      super(protocolFactory, clientManager, transport);
    }

    public void createDomain(org.apache.airavata.sharing.registry.models.Domain domain, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      createDomain_call method_call = new createDomain_call(domain, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class createDomain_call extends org.apache.thrift.async.TAsyncMethodCall {
      private org.apache.airavata.sharing.registry.models.Domain domain;
      public createDomain_call(org.apache.airavata.sharing.registry.models.Domain domain, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domain = domain;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("createDomain", org.apache.thrift.protocol.TMessageType.CALL, 0));
        createDomain_args args = new createDomain_args();
        args.setDomain(domain);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public String getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_createDomain();
      }
    }

    public void updateDomain(org.apache.airavata.sharing.registry.models.Domain domain, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      updateDomain_call method_call = new updateDomain_call(domain, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class updateDomain_call extends org.apache.thrift.async.TAsyncMethodCall {
      private org.apache.airavata.sharing.registry.models.Domain domain;
      public updateDomain_call(org.apache.airavata.sharing.registry.models.Domain domain, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domain = domain;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("updateDomain", org.apache.thrift.protocol.TMessageType.CALL, 0));
        updateDomain_args args = new updateDomain_args();
        args.setDomain(domain);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_updateDomain();
      }
    }

    public void isDomainExists(String domainId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      isDomainExists_call method_call = new isDomainExists_call(domainId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class isDomainExists_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      public isDomainExists_call(String domainId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("isDomainExists", org.apache.thrift.protocol.TMessageType.CALL, 0));
        isDomainExists_args args = new isDomainExists_args();
        args.setDomainId(domainId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_isDomainExists();
      }
    }

    public void deleteDomain(String domainId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      deleteDomain_call method_call = new deleteDomain_call(domainId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class deleteDomain_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      public deleteDomain_call(String domainId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("deleteDomain", org.apache.thrift.protocol.TMessageType.CALL, 0));
        deleteDomain_args args = new deleteDomain_args();
        args.setDomainId(domainId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_deleteDomain();
      }
    }

    public void getDomain(String domainId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getDomain_call method_call = new getDomain_call(domainId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getDomain_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      public getDomain_call(String domainId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getDomain", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getDomain_args args = new getDomain_args();
        args.setDomainId(domainId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public org.apache.airavata.sharing.registry.models.Domain getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getDomain();
      }
    }

    public void getDomains(int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getDomains_call method_call = new getDomains_call(offset, limit, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getDomains_call extends org.apache.thrift.async.TAsyncMethodCall {
      private int offset;
      private int limit;
      public getDomains_call(int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.offset = offset;
        this.limit = limit;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getDomains", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getDomains_args args = new getDomains_args();
        args.setOffset(offset);
        args.setLimit(limit);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<org.apache.airavata.sharing.registry.models.Domain> getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getDomains();
      }
    }

    public void createUser(org.apache.airavata.sharing.registry.models.User user, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      createUser_call method_call = new createUser_call(user, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class createUser_call extends org.apache.thrift.async.TAsyncMethodCall {
      private org.apache.airavata.sharing.registry.models.User user;
      public createUser_call(org.apache.airavata.sharing.registry.models.User user, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.user = user;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("createUser", org.apache.thrift.protocol.TMessageType.CALL, 0));
        createUser_args args = new createUser_args();
        args.setUser(user);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public String getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_createUser();
      }
    }

    public void updatedUser(org.apache.airavata.sharing.registry.models.User user, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      updatedUser_call method_call = new updatedUser_call(user, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class updatedUser_call extends org.apache.thrift.async.TAsyncMethodCall {
      private org.apache.airavata.sharing.registry.models.User user;
      public updatedUser_call(org.apache.airavata.sharing.registry.models.User user, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.user = user;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("updatedUser", org.apache.thrift.protocol.TMessageType.CALL, 0));
        updatedUser_args args = new updatedUser_args();
        args.setUser(user);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_updatedUser();
      }
    }

    public void isUserExists(String domainId, String userId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      isUserExists_call method_call = new isUserExists_call(domainId, userId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class isUserExists_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String userId;
      public isUserExists_call(String domainId, String userId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.userId = userId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("isUserExists", org.apache.thrift.protocol.TMessageType.CALL, 0));
        isUserExists_args args = new isUserExists_args();
        args.setDomainId(domainId);
        args.setUserId(userId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_isUserExists();
      }
    }

    public void deleteUser(String domainId, String userId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      deleteUser_call method_call = new deleteUser_call(domainId, userId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class deleteUser_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String userId;
      public deleteUser_call(String domainId, String userId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.userId = userId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("deleteUser", org.apache.thrift.protocol.TMessageType.CALL, 0));
        deleteUser_args args = new deleteUser_args();
        args.setDomainId(domainId);
        args.setUserId(userId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_deleteUser();
      }
    }

    public void getUser(String domainId, String userId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getUser_call method_call = new getUser_call(domainId, userId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getUser_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String userId;
      public getUser_call(String domainId, String userId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.userId = userId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getUser", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getUser_args args = new getUser_args();
        args.setDomainId(domainId);
        args.setUserId(userId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public org.apache.airavata.sharing.registry.models.User getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getUser();
      }
    }

    public void getUsers(String domainId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getUsers_call method_call = new getUsers_call(domainId, offset, limit, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getUsers_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private int offset;
      private int limit;
      public getUsers_call(String domainId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.offset = offset;
        this.limit = limit;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getUsers", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getUsers_args args = new getUsers_args();
        args.setDomainId(domainId);
        args.setOffset(offset);
        args.setLimit(limit);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<org.apache.airavata.sharing.registry.models.User> getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getUsers();
      }
    }

    public void createGroup(org.apache.airavata.sharing.registry.models.UserGroup group, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      createGroup_call method_call = new createGroup_call(group, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class createGroup_call extends org.apache.thrift.async.TAsyncMethodCall {
      private org.apache.airavata.sharing.registry.models.UserGroup group;
      public createGroup_call(org.apache.airavata.sharing.registry.models.UserGroup group, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.group = group;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("createGroup", org.apache.thrift.protocol.TMessageType.CALL, 0));
        createGroup_args args = new createGroup_args();
        args.setGroup(group);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public String getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_createGroup();
      }
    }

    public void updateGroup(org.apache.airavata.sharing.registry.models.UserGroup group, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      updateGroup_call method_call = new updateGroup_call(group, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class updateGroup_call extends org.apache.thrift.async.TAsyncMethodCall {
      private org.apache.airavata.sharing.registry.models.UserGroup group;
      public updateGroup_call(org.apache.airavata.sharing.registry.models.UserGroup group, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.group = group;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("updateGroup", org.apache.thrift.protocol.TMessageType.CALL, 0));
        updateGroup_args args = new updateGroup_args();
        args.setGroup(group);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_updateGroup();
      }
    }

    public void isGroupExists(String domainId, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      isGroupExists_call method_call = new isGroupExists_call(domainId, groupId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class isGroupExists_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String groupId;
      public isGroupExists_call(String domainId, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.groupId = groupId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("isGroupExists", org.apache.thrift.protocol.TMessageType.CALL, 0));
        isGroupExists_args args = new isGroupExists_args();
        args.setDomainId(domainId);
        args.setGroupId(groupId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_isGroupExists();
      }
    }

    public void deleteGroup(String domainId, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      deleteGroup_call method_call = new deleteGroup_call(domainId, groupId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class deleteGroup_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String groupId;
      public deleteGroup_call(String domainId, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.groupId = groupId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("deleteGroup", org.apache.thrift.protocol.TMessageType.CALL, 0));
        deleteGroup_args args = new deleteGroup_args();
        args.setDomainId(domainId);
        args.setGroupId(groupId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_deleteGroup();
      }
    }

    public void getGroup(String domainId, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getGroup_call method_call = new getGroup_call(domainId, groupId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getGroup_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String groupId;
      public getGroup_call(String domainId, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.groupId = groupId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getGroup", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getGroup_args args = new getGroup_args();
        args.setDomainId(domainId);
        args.setGroupId(groupId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public org.apache.airavata.sharing.registry.models.UserGroup getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getGroup();
      }
    }

    public void getGroups(String domainId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getGroups_call method_call = new getGroups_call(domainId, offset, limit, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getGroups_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private int offset;
      private int limit;
      public getGroups_call(String domainId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.offset = offset;
        this.limit = limit;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getGroups", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getGroups_args args = new getGroups_args();
        args.setDomainId(domainId);
        args.setOffset(offset);
        args.setLimit(limit);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<org.apache.airavata.sharing.registry.models.UserGroup> getResult() throws org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getGroups();
      }
    }

    public void addUsersToGroup(String domainId, List<String> userIds, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      addUsersToGroup_call method_call = new addUsersToGroup_call(domainId, userIds, groupId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class addUsersToGroup_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private List<String> userIds;
      private String groupId;
      public addUsersToGroup_call(String domainId, List<String> userIds, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.userIds = userIds;
        this.groupId = groupId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("addUsersToGroup", org.apache.thrift.protocol.TMessageType.CALL, 0));
        addUsersToGroup_args args = new addUsersToGroup_args();
        args.setDomainId(domainId);
        args.setUserIds(userIds);
        args.setGroupId(groupId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_addUsersToGroup();
      }
    }

    public void removeUsersFromGroup(String domainId, List<String> userIds, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      removeUsersFromGroup_call method_call = new removeUsersFromGroup_call(domainId, userIds, groupId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class removeUsersFromGroup_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private List<String> userIds;
      private String groupId;
      public removeUsersFromGroup_call(String domainId, List<String> userIds, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.userIds = userIds;
        this.groupId = groupId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("removeUsersFromGroup", org.apache.thrift.protocol.TMessageType.CALL, 0));
        removeUsersFromGroup_args args = new removeUsersFromGroup_args();
        args.setDomainId(domainId);
        args.setUserIds(userIds);
        args.setGroupId(groupId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_removeUsersFromGroup();
      }
    }

    public void getGroupMembersOfTypeUser(String domainId, String groupId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getGroupMembersOfTypeUser_call method_call = new getGroupMembersOfTypeUser_call(domainId, groupId, offset, limit, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getGroupMembersOfTypeUser_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String groupId;
      private int offset;
      private int limit;
      public getGroupMembersOfTypeUser_call(String domainId, String groupId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.groupId = groupId;
        this.offset = offset;
        this.limit = limit;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getGroupMembersOfTypeUser", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getGroupMembersOfTypeUser_args args = new getGroupMembersOfTypeUser_args();
        args.setDomainId(domainId);
        args.setGroupId(groupId);
        args.setOffset(offset);
        args.setLimit(limit);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<org.apache.airavata.sharing.registry.models.User> getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getGroupMembersOfTypeUser();
      }
    }

    public void getGroupMembersOfTypeGroup(String domainId, String groupId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getGroupMembersOfTypeGroup_call method_call = new getGroupMembersOfTypeGroup_call(domainId, groupId, offset, limit, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getGroupMembersOfTypeGroup_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String groupId;
      private int offset;
      private int limit;
      public getGroupMembersOfTypeGroup_call(String domainId, String groupId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.groupId = groupId;
        this.offset = offset;
        this.limit = limit;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getGroupMembersOfTypeGroup", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getGroupMembersOfTypeGroup_args args = new getGroupMembersOfTypeGroup_args();
        args.setDomainId(domainId);
        args.setGroupId(groupId);
        args.setOffset(offset);
        args.setLimit(limit);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<org.apache.airavata.sharing.registry.models.UserGroup> getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getGroupMembersOfTypeGroup();
      }
    }

    public void addChildGroupsToParentGroup(String domainId, List<String> childIds, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      addChildGroupsToParentGroup_call method_call = new addChildGroupsToParentGroup_call(domainId, childIds, groupId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class addChildGroupsToParentGroup_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private List<String> childIds;
      private String groupId;
      public addChildGroupsToParentGroup_call(String domainId, List<String> childIds, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.childIds = childIds;
        this.groupId = groupId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("addChildGroupsToParentGroup", org.apache.thrift.protocol.TMessageType.CALL, 0));
        addChildGroupsToParentGroup_args args = new addChildGroupsToParentGroup_args();
        args.setDomainId(domainId);
        args.setChildIds(childIds);
        args.setGroupId(groupId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_addChildGroupsToParentGroup();
      }
    }

    public void removeChildGroupFromParentGroup(String domainId, String childId, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      removeChildGroupFromParentGroup_call method_call = new removeChildGroupFromParentGroup_call(domainId, childId, groupId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class removeChildGroupFromParentGroup_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String childId;
      private String groupId;
      public removeChildGroupFromParentGroup_call(String domainId, String childId, String groupId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.childId = childId;
        this.groupId = groupId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("removeChildGroupFromParentGroup", org.apache.thrift.protocol.TMessageType.CALL, 0));
        removeChildGroupFromParentGroup_args args = new removeChildGroupFromParentGroup_args();
        args.setDomainId(domainId);
        args.setChildId(childId);
        args.setGroupId(groupId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_removeChildGroupFromParentGroup();
      }
    }

    public void getAllMemberGroupsForUser(String domainId, String userId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getAllMemberGroupsForUser_call method_call = new getAllMemberGroupsForUser_call(domainId, userId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getAllMemberGroupsForUser_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String userId;
      public getAllMemberGroupsForUser_call(String domainId, String userId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.userId = userId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getAllMemberGroupsForUser", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getAllMemberGroupsForUser_args args = new getAllMemberGroupsForUser_args();
        args.setDomainId(domainId);
        args.setUserId(userId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<org.apache.airavata.sharing.registry.models.UserGroup> getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getAllMemberGroupsForUser();
      }
    }

    public void createEntityType(org.apache.airavata.sharing.registry.models.EntityType entityType, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      createEntityType_call method_call = new createEntityType_call(entityType, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class createEntityType_call extends org.apache.thrift.async.TAsyncMethodCall {
      private org.apache.airavata.sharing.registry.models.EntityType entityType;
      public createEntityType_call(org.apache.airavata.sharing.registry.models.EntityType entityType, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.entityType = entityType;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("createEntityType", org.apache.thrift.protocol.TMessageType.CALL, 0));
        createEntityType_args args = new createEntityType_args();
        args.setEntityType(entityType);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public String getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_createEntityType();
      }
    }

    public void updateEntityType(org.apache.airavata.sharing.registry.models.EntityType entityType, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      updateEntityType_call method_call = new updateEntityType_call(entityType, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class updateEntityType_call extends org.apache.thrift.async.TAsyncMethodCall {
      private org.apache.airavata.sharing.registry.models.EntityType entityType;
      public updateEntityType_call(org.apache.airavata.sharing.registry.models.EntityType entityType, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.entityType = entityType;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("updateEntityType", org.apache.thrift.protocol.TMessageType.CALL, 0));
        updateEntityType_args args = new updateEntityType_args();
        args.setEntityType(entityType);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_updateEntityType();
      }
    }

    public void isEntityTypeExists(String domainId, String entityTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      isEntityTypeExists_call method_call = new isEntityTypeExists_call(domainId, entityTypeId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class isEntityTypeExists_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String entityTypeId;
      public isEntityTypeExists_call(String domainId, String entityTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.entityTypeId = entityTypeId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("isEntityTypeExists", org.apache.thrift.protocol.TMessageType.CALL, 0));
        isEntityTypeExists_args args = new isEntityTypeExists_args();
        args.setDomainId(domainId);
        args.setEntityTypeId(entityTypeId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_isEntityTypeExists();
      }
    }

    public void deleteEntityType(String domainId, String entityTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      deleteEntityType_call method_call = new deleteEntityType_call(domainId, entityTypeId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class deleteEntityType_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String entityTypeId;
      public deleteEntityType_call(String domainId, String entityTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.entityTypeId = entityTypeId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("deleteEntityType", org.apache.thrift.protocol.TMessageType.CALL, 0));
        deleteEntityType_args args = new deleteEntityType_args();
        args.setDomainId(domainId);
        args.setEntityTypeId(entityTypeId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_deleteEntityType();
      }
    }

    public void getEntityType(String domainId, String entityTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getEntityType_call method_call = new getEntityType_call(domainId, entityTypeId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getEntityType_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String entityTypeId;
      public getEntityType_call(String domainId, String entityTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.entityTypeId = entityTypeId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getEntityType", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getEntityType_args args = new getEntityType_args();
        args.setDomainId(domainId);
        args.setEntityTypeId(entityTypeId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public org.apache.airavata.sharing.registry.models.EntityType getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getEntityType();
      }
    }

    public void getEntityTypes(String domainId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getEntityTypes_call method_call = new getEntityTypes_call(domainId, offset, limit, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getEntityTypes_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private int offset;
      private int limit;
      public getEntityTypes_call(String domainId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.offset = offset;
        this.limit = limit;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getEntityTypes", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getEntityTypes_args args = new getEntityTypes_args();
        args.setDomainId(domainId);
        args.setOffset(offset);
        args.setLimit(limit);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<org.apache.airavata.sharing.registry.models.EntityType> getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getEntityTypes();
      }
    }

    public void createEntity(org.apache.airavata.sharing.registry.models.Entity entity, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      createEntity_call method_call = new createEntity_call(entity, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class createEntity_call extends org.apache.thrift.async.TAsyncMethodCall {
      private org.apache.airavata.sharing.registry.models.Entity entity;
      public createEntity_call(org.apache.airavata.sharing.registry.models.Entity entity, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.entity = entity;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("createEntity", org.apache.thrift.protocol.TMessageType.CALL, 0));
        createEntity_args args = new createEntity_args();
        args.setEntity(entity);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public String getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_createEntity();
      }
    }

    public void updateEntity(org.apache.airavata.sharing.registry.models.Entity entity, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      updateEntity_call method_call = new updateEntity_call(entity, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class updateEntity_call extends org.apache.thrift.async.TAsyncMethodCall {
      private org.apache.airavata.sharing.registry.models.Entity entity;
      public updateEntity_call(org.apache.airavata.sharing.registry.models.Entity entity, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.entity = entity;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("updateEntity", org.apache.thrift.protocol.TMessageType.CALL, 0));
        updateEntity_args args = new updateEntity_args();
        args.setEntity(entity);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_updateEntity();
      }
    }

    public void isEntityExists(String domainId, String entityId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      isEntityExists_call method_call = new isEntityExists_call(domainId, entityId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class isEntityExists_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String entityId;
      public isEntityExists_call(String domainId, String entityId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.entityId = entityId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("isEntityExists", org.apache.thrift.protocol.TMessageType.CALL, 0));
        isEntityExists_args args = new isEntityExists_args();
        args.setDomainId(domainId);
        args.setEntityId(entityId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_isEntityExists();
      }
    }

    public void deleteEntity(String domainId, String entityId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      deleteEntity_call method_call = new deleteEntity_call(domainId, entityId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class deleteEntity_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String entityId;
      public deleteEntity_call(String domainId, String entityId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.entityId = entityId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("deleteEntity", org.apache.thrift.protocol.TMessageType.CALL, 0));
        deleteEntity_args args = new deleteEntity_args();
        args.setDomainId(domainId);
        args.setEntityId(entityId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_deleteEntity();
      }
    }

    public void getEntity(String domainId, String entityId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getEntity_call method_call = new getEntity_call(domainId, entityId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getEntity_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String entityId;
      public getEntity_call(String domainId, String entityId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.entityId = entityId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getEntity", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getEntity_args args = new getEntity_args();
        args.setDomainId(domainId);
        args.setEntityId(entityId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public org.apache.airavata.sharing.registry.models.Entity getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getEntity();
      }
    }

    public void searchEntities(String domainId, String userId, List<org.apache.airavata.sharing.registry.models.SearchCriteria> filters, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      searchEntities_call method_call = new searchEntities_call(domainId, userId, filters, offset, limit, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class searchEntities_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String userId;
      private List<org.apache.airavata.sharing.registry.models.SearchCriteria> filters;
      private int offset;
      private int limit;
      public searchEntities_call(String domainId, String userId, List<org.apache.airavata.sharing.registry.models.SearchCriteria> filters, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.userId = userId;
        this.filters = filters;
        this.offset = offset;
        this.limit = limit;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("searchEntities", org.apache.thrift.protocol.TMessageType.CALL, 0));
        searchEntities_args args = new searchEntities_args();
        args.setDomainId(domainId);
        args.setUserId(userId);
        args.setFilters(filters);
        args.setOffset(offset);
        args.setLimit(limit);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<org.apache.airavata.sharing.registry.models.Entity> getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_searchEntities();
      }
    }

    public void getListOfSharedUsers(String domainId, String entityId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getListOfSharedUsers_call method_call = new getListOfSharedUsers_call(domainId, entityId, permissionTypeId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getListOfSharedUsers_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String entityId;
      private String permissionTypeId;
      public getListOfSharedUsers_call(String domainId, String entityId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.entityId = entityId;
        this.permissionTypeId = permissionTypeId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getListOfSharedUsers", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getListOfSharedUsers_args args = new getListOfSharedUsers_args();
        args.setDomainId(domainId);
        args.setEntityId(entityId);
        args.setPermissionTypeId(permissionTypeId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<org.apache.airavata.sharing.registry.models.User> getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getListOfSharedUsers();
      }
    }

    public void getListOfSharedGroups(String domainId, String entityId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getListOfSharedGroups_call method_call = new getListOfSharedGroups_call(domainId, entityId, permissionTypeId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getListOfSharedGroups_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String entityId;
      private String permissionTypeId;
      public getListOfSharedGroups_call(String domainId, String entityId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.entityId = entityId;
        this.permissionTypeId = permissionTypeId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getListOfSharedGroups", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getListOfSharedGroups_args args = new getListOfSharedGroups_args();
        args.setDomainId(domainId);
        args.setEntityId(entityId);
        args.setPermissionTypeId(permissionTypeId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<org.apache.airavata.sharing.registry.models.UserGroup> getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getListOfSharedGroups();
      }
    }

    public void createPermissionType(org.apache.airavata.sharing.registry.models.PermissionType permissionType, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      createPermissionType_call method_call = new createPermissionType_call(permissionType, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class createPermissionType_call extends org.apache.thrift.async.TAsyncMethodCall {
      private org.apache.airavata.sharing.registry.models.PermissionType permissionType;
      public createPermissionType_call(org.apache.airavata.sharing.registry.models.PermissionType permissionType, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.permissionType = permissionType;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("createPermissionType", org.apache.thrift.protocol.TMessageType.CALL, 0));
        createPermissionType_args args = new createPermissionType_args();
        args.setPermissionType(permissionType);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public String getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.airavata.sharing.registry.models.DuplicateEntryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_createPermissionType();
      }
    }

    public void updatePermissionType(org.apache.airavata.sharing.registry.models.PermissionType permissionType, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      updatePermissionType_call method_call = new updatePermissionType_call(permissionType, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class updatePermissionType_call extends org.apache.thrift.async.TAsyncMethodCall {
      private org.apache.airavata.sharing.registry.models.PermissionType permissionType;
      public updatePermissionType_call(org.apache.airavata.sharing.registry.models.PermissionType permissionType, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.permissionType = permissionType;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("updatePermissionType", org.apache.thrift.protocol.TMessageType.CALL, 0));
        updatePermissionType_args args = new updatePermissionType_args();
        args.setPermissionType(permissionType);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_updatePermissionType();
      }
    }

    public void isPermissionExists(String dimainId, String permissionId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      isPermissionExists_call method_call = new isPermissionExists_call(dimainId, permissionId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class isPermissionExists_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String dimainId;
      private String permissionId;
      public isPermissionExists_call(String dimainId, String permissionId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.dimainId = dimainId;
        this.permissionId = permissionId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("isPermissionExists", org.apache.thrift.protocol.TMessageType.CALL, 0));
        isPermissionExists_args args = new isPermissionExists_args();
        args.setDimainId(dimainId);
        args.setPermissionId(permissionId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_isPermissionExists();
      }
    }

    public void deletePermissionType(String domainId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      deletePermissionType_call method_call = new deletePermissionType_call(domainId, permissionTypeId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class deletePermissionType_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String permissionTypeId;
      public deletePermissionType_call(String domainId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.permissionTypeId = permissionTypeId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("deletePermissionType", org.apache.thrift.protocol.TMessageType.CALL, 0));
        deletePermissionType_args args = new deletePermissionType_args();
        args.setDomainId(domainId);
        args.setPermissionTypeId(permissionTypeId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_deletePermissionType();
      }
    }

    public void getPermissionType(String domainId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getPermissionType_call method_call = new getPermissionType_call(domainId, permissionTypeId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getPermissionType_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String permissionTypeId;
      public getPermissionType_call(String domainId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.permissionTypeId = permissionTypeId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getPermissionType", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getPermissionType_args args = new getPermissionType_args();
        args.setDomainId(domainId);
        args.setPermissionTypeId(permissionTypeId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public org.apache.airavata.sharing.registry.models.PermissionType getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getPermissionType();
      }
    }

    public void getPermissionTypes(String domainId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      getPermissionTypes_call method_call = new getPermissionTypes_call(domainId, offset, limit, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class getPermissionTypes_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private int offset;
      private int limit;
      public getPermissionTypes_call(String domainId, int offset, int limit, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.offset = offset;
        this.limit = limit;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getPermissionTypes", org.apache.thrift.protocol.TMessageType.CALL, 0));
        getPermissionTypes_args args = new getPermissionTypes_args();
        args.setDomainId(domainId);
        args.setOffset(offset);
        args.setLimit(limit);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public List<org.apache.airavata.sharing.registry.models.PermissionType> getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_getPermissionTypes();
      }
    }

    public void shareEntityWithUsers(String domainId, String entityId, List<String> userList, String perssionTypeId, boolean cascadePermission, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      shareEntityWithUsers_call method_call = new shareEntityWithUsers_call(domainId, entityId, userList, perssionTypeId, cascadePermission, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class shareEntityWithUsers_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String entityId;
      private List<String> userList;
      private String perssionTypeId;
      private boolean cascadePermission;
      public shareEntityWithUsers_call(String domainId, String entityId, List<String> userList, String perssionTypeId, boolean cascadePermission, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.entityId = entityId;
        this.userList = userList;
        this.perssionTypeId = perssionTypeId;
        this.cascadePermission = cascadePermission;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("shareEntityWithUsers", org.apache.thrift.protocol.TMessageType.CALL, 0));
        shareEntityWithUsers_args args = new shareEntityWithUsers_args();
        args.setDomainId(domainId);
        args.setEntityId(entityId);
        args.setUserList(userList);
        args.setPerssionTypeId(perssionTypeId);
        args.setCascadePermission(cascadePermission);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_shareEntityWithUsers();
      }
    }

    public void revokeEntitySharingFromUsers(String domainId, String entityId, List<String> userList, String perssionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      revokeEntitySharingFromUsers_call method_call = new revokeEntitySharingFromUsers_call(domainId, entityId, userList, perssionTypeId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class revokeEntitySharingFromUsers_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String entityId;
      private List<String> userList;
      private String perssionTypeId;
      public revokeEntitySharingFromUsers_call(String domainId, String entityId, List<String> userList, String perssionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.entityId = entityId;
        this.userList = userList;
        this.perssionTypeId = perssionTypeId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("revokeEntitySharingFromUsers", org.apache.thrift.protocol.TMessageType.CALL, 0));
        revokeEntitySharingFromUsers_args args = new revokeEntitySharingFromUsers_args();
        args.setDomainId(domainId);
        args.setEntityId(entityId);
        args.setUserList(userList);
        args.setPerssionTypeId(perssionTypeId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_revokeEntitySharingFromUsers();
      }
    }

    public void shareEntityWithGroups(String domainId, String entityId, List<String> groupList, String perssionTypeId, boolean cascadePermission, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      shareEntityWithGroups_call method_call = new shareEntityWithGroups_call(domainId, entityId, groupList, perssionTypeId, cascadePermission, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class shareEntityWithGroups_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String entityId;
      private List<String> groupList;
      private String perssionTypeId;
      private boolean cascadePermission;
      public shareEntityWithGroups_call(String domainId, String entityId, List<String> groupList, String perssionTypeId, boolean cascadePermission, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.entityId = entityId;
        this.groupList = groupList;
        this.perssionTypeId = perssionTypeId;
        this.cascadePermission = cascadePermission;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("shareEntityWithGroups", org.apache.thrift.protocol.TMessageType.CALL, 0));
        shareEntityWithGroups_args args = new shareEntityWithGroups_args();
        args.setDomainId(domainId);
        args.setEntityId(entityId);
        args.setGroupList(groupList);
        args.setPerssionTypeId(perssionTypeId);
        args.setCascadePermission(cascadePermission);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_shareEntityWithGroups();
      }
    }

    public void revokeEntitySharingFromGroups(String domainId, String entityId, List<String> groupList, String perssionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      revokeEntitySharingFromGroups_call method_call = new revokeEntitySharingFromGroups_call(domainId, entityId, groupList, perssionTypeId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class revokeEntitySharingFromGroups_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String entityId;
      private List<String> groupList;
      private String perssionTypeId;
      public revokeEntitySharingFromGroups_call(String domainId, String entityId, List<String> groupList, String perssionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.entityId = entityId;
        this.groupList = groupList;
        this.perssionTypeId = perssionTypeId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("revokeEntitySharingFromGroups", org.apache.thrift.protocol.TMessageType.CALL, 0));
        revokeEntitySharingFromGroups_args args = new revokeEntitySharingFromGroups_args();
        args.setDomainId(domainId);
        args.setEntityId(entityId);
        args.setGroupList(groupList);
        args.setPerssionTypeId(perssionTypeId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_revokeEntitySharingFromGroups();
      }
    }

    public void userHasAccess(String domainId, String userId, String entityId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
      checkReady();
      userHasAccess_call method_call = new userHasAccess_call(domainId, userId, entityId, permissionTypeId, resultHandler, this, ___protocolFactory, ___transport);
      this.___currentMethod = method_call;
      ___manager.call(method_call);
    }

    public static class userHasAccess_call extends org.apache.thrift.async.TAsyncMethodCall {
      private String domainId;
      private String userId;
      private String entityId;
      private String permissionTypeId;
      public userHasAccess_call(String domainId, String userId, String entityId, String permissionTypeId, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
        super(client, protocolFactory, transport, resultHandler, false);
        this.domainId = domainId;
        this.userId = userId;
        this.entityId = entityId;
        this.permissionTypeId = permissionTypeId;
      }

      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("userHasAccess", org.apache.thrift.protocol.TMessageType.CALL, 0));
        userHasAccess_args args = new userHasAccess_args();
        args.setDomainId(domainId);
        args.setUserId(userId);
        args.setEntityId(entityId);
        args.setPermissionTypeId(permissionTypeId);
        args.write(prot);
        prot.writeMessageEnd();
      }

      public boolean getResult() throws org.apache.airavata.sharing.registry.models.SharingRegistryException, org.apache.thrift.TException {
        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
          throw new IllegalStateException("Method call not finished!");
        }
        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
        return (new Client(prot)).recv_userHasAccess();
      }
    }

  }

  public static class Processor<I extends Iface> extends org.apache.thrift.TBaseProcessor<I> implements org.apache.thrift.TProcessor {
    private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class.getName());
    public Processor(I iface) {
      super(iface, getProcessMap(new HashMap<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>>()));
    }

    protected Processor(I iface, Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> processMap) {
      super(iface, getProcessMap(processMap));
    }

    private static <I extends Iface> Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> getProcessMap(Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> processMap) {
      processMap.put("createDomain", new createDomain());
      processMap.put("updateDomain", new updateDomain());
      processMap.put("isDomainExists", new isDomainExists());
      processMap.put("deleteDomain", new deleteDomain());
      processMap.put("getDomain", new getDomain());
      processMap.put("getDomains", new getDomains());
      processMap.put("createUser", new createUser());
      processMap.put("updatedUser", new updatedUser());
      processMap.put("isUserExists", new isUserExists());
      processMap.put("deleteUser", new deleteUser());
      processMap.put("getUser", new getUser());
      processMap.put("getUsers", new getUsers());
      processMap.put("createGroup", new createGroup());
      processMap.put("updateGroup", new updateGroup());
      processMap.put("isGroupExists", new isGroupExists());
      processMap.put("deleteGroup", new deleteGroup());
      processMap.put("getGroup", new getGroup());
      processMap.put("getGroups", new getGroups());
      processMap.put("addUsersToGroup", new addUsersToGroup());
      processMap.put("removeUsersFromGroup", new removeUsersFromGroup());
      processMap.put("getGroupMembersOfTypeUser", new getGroupMembersOfTypeUser());
      processMap.put("getGroupMembersOfTypeGroup", new getGroupMembersOfTypeGroup());
      processMap.put("addChildGroupsToParentGroup", new addChildGroupsToParentGroup());
      processMap.put("removeChildGroupFromParentGroup", new removeChildGroupFromParentGroup());
      processMap.put("getAllMemberGroupsForUser", new getAllMemberGroupsForUser());
      processMap.put("createEntityType", new createEntityType());
      processMap.put("updateEntityType", new updateEntityType());
      processMap.put("isEntityTypeExists", new isEntityTypeExists());
      processMap.put("deleteEntityType", new deleteEntityType());
      processMap.put("getEntityType", new getEntityType());
      processMap.put("getEntityTypes", new getEntityTypes());
      processMap.put("createEntity", new createEntity());
      processMap.put("updateEntity", new updateEntity());
      processMap.put("isEntityExists", new isEntityExists());
      processMap.put("deleteEntity", new deleteEntity());
      processMap.put("getEntity", new getEntity());
      processMap.put("searchEntities", new searchEntities());
      processMap.put("getListOfSharedUsers", new getListOfSharedUsers());
      processMap.put("getListOfSharedGroups", new getListOfSharedGroups());
      processMap.put("createPermissionType", new createPermissionType());
      processMap.put("updatePermissionType", new updatePermissionType());
      processMap.put("isPermissionExists", new isPermissionExists());
      processMap.put("deletePermissionType", new deletePermissionType());
      processMap.put("getPermissionType", new getPermissionType());
      processMap.put("getPermissionTypes", new getPermissionTypes());
      processMap.put("shareEntityWithUsers", new shareEntityWithUsers());
      processMap.put("revokeEntitySharingFromUsers", new revokeEntitySharingFromUsers());
      processMap.put("shareEntityWithGroups", new shareEntityWithGroups());
      processMap.put("revokeEntitySharingFromGroups", new revokeEntitySharingFromGroups());
      processMap.put("userHasAccess", new userHasAccess());
      return processMap;
    }

    public static class createDomain<I extends Iface> extends org.apache.thrift.ProcessFunction<I, createDomain_args> {
      public createDomain() {
        super("createDomain");
      }

      public createDomain_args getEmptyArgsInstance() {
        return new createDomain_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public createDomain_result getResult(I iface, createDomain_args args) throws org.apache.thrift.TException {
        createDomain_result result = new createDomain_result();
        try {
          result.success = iface.createDomain(args.domain);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        } catch (org.apache.airavata.sharing.registry.models.DuplicateEntryException dee) {
          result.dee = dee;
        }
        return result;
      }
    }

    public static class updateDomain<I extends Iface> extends org.apache.thrift.ProcessFunction<I, updateDomain_args> {
      public updateDomain() {
        super("updateDomain");
      }

      public updateDomain_args getEmptyArgsInstance() {
        return new updateDomain_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public updateDomain_result getResult(I iface, updateDomain_args args) throws org.apache.thrift.TException {
        updateDomain_result result = new updateDomain_result();
        try {
          result.success = iface.updateDomain(args.domain);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class isDomainExists<I extends Iface> extends org.apache.thrift.ProcessFunction<I, isDomainExists_args> {
      public isDomainExists() {
        super("isDomainExists");
      }

      public isDomainExists_args getEmptyArgsInstance() {
        return new isDomainExists_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public isDomainExists_result getResult(I iface, isDomainExists_args args) throws org.apache.thrift.TException {
        isDomainExists_result result = new isDomainExists_result();
        try {
          result.success = iface.isDomainExists(args.domainId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class deleteDomain<I extends Iface> extends org.apache.thrift.ProcessFunction<I, deleteDomain_args> {
      public deleteDomain() {
        super("deleteDomain");
      }

      public deleteDomain_args getEmptyArgsInstance() {
        return new deleteDomain_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public deleteDomain_result getResult(I iface, deleteDomain_args args) throws org.apache.thrift.TException {
        deleteDomain_result result = new deleteDomain_result();
        try {
          result.success = iface.deleteDomain(args.domainId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getDomain<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getDomain_args> {
      public getDomain() {
        super("getDomain");
      }

      public getDomain_args getEmptyArgsInstance() {
        return new getDomain_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getDomain_result getResult(I iface, getDomain_args args) throws org.apache.thrift.TException {
        getDomain_result result = new getDomain_result();
        try {
          result.success = iface.getDomain(args.domainId);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getDomains<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getDomains_args> {
      public getDomains() {
        super("getDomains");
      }

      public getDomains_args getEmptyArgsInstance() {
        return new getDomains_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getDomains_result getResult(I iface, getDomains_args args) throws org.apache.thrift.TException {
        getDomains_result result = new getDomains_result();
        try {
          result.success = iface.getDomains(args.offset, args.limit);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class createUser<I extends Iface> extends org.apache.thrift.ProcessFunction<I, createUser_args> {
      public createUser() {
        super("createUser");
      }

      public createUser_args getEmptyArgsInstance() {
        return new createUser_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public createUser_result getResult(I iface, createUser_args args) throws org.apache.thrift.TException {
        createUser_result result = new createUser_result();
        try {
          result.success = iface.createUser(args.user);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        } catch (org.apache.airavata.sharing.registry.models.DuplicateEntryException dee) {
          result.dee = dee;
        }
        return result;
      }
    }

    public static class updatedUser<I extends Iface> extends org.apache.thrift.ProcessFunction<I, updatedUser_args> {
      public updatedUser() {
        super("updatedUser");
      }

      public updatedUser_args getEmptyArgsInstance() {
        return new updatedUser_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public updatedUser_result getResult(I iface, updatedUser_args args) throws org.apache.thrift.TException {
        updatedUser_result result = new updatedUser_result();
        try {
          result.success = iface.updatedUser(args.user);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class isUserExists<I extends Iface> extends org.apache.thrift.ProcessFunction<I, isUserExists_args> {
      public isUserExists() {
        super("isUserExists");
      }

      public isUserExists_args getEmptyArgsInstance() {
        return new isUserExists_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public isUserExists_result getResult(I iface, isUserExists_args args) throws org.apache.thrift.TException {
        isUserExists_result result = new isUserExists_result();
        try {
          result.success = iface.isUserExists(args.domainId, args.userId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class deleteUser<I extends Iface> extends org.apache.thrift.ProcessFunction<I, deleteUser_args> {
      public deleteUser() {
        super("deleteUser");
      }

      public deleteUser_args getEmptyArgsInstance() {
        return new deleteUser_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public deleteUser_result getResult(I iface, deleteUser_args args) throws org.apache.thrift.TException {
        deleteUser_result result = new deleteUser_result();
        try {
          result.success = iface.deleteUser(args.domainId, args.userId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getUser<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getUser_args> {
      public getUser() {
        super("getUser");
      }

      public getUser_args getEmptyArgsInstance() {
        return new getUser_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getUser_result getResult(I iface, getUser_args args) throws org.apache.thrift.TException {
        getUser_result result = new getUser_result();
        try {
          result.success = iface.getUser(args.domainId, args.userId);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getUsers<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getUsers_args> {
      public getUsers() {
        super("getUsers");
      }

      public getUsers_args getEmptyArgsInstance() {
        return new getUsers_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getUsers_result getResult(I iface, getUsers_args args) throws org.apache.thrift.TException {
        getUsers_result result = new getUsers_result();
        try {
          result.success = iface.getUsers(args.domainId, args.offset, args.limit);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class createGroup<I extends Iface> extends org.apache.thrift.ProcessFunction<I, createGroup_args> {
      public createGroup() {
        super("createGroup");
      }

      public createGroup_args getEmptyArgsInstance() {
        return new createGroup_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public createGroup_result getResult(I iface, createGroup_args args) throws org.apache.thrift.TException {
        createGroup_result result = new createGroup_result();
        try {
          result.success = iface.createGroup(args.group);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class updateGroup<I extends Iface> extends org.apache.thrift.ProcessFunction<I, updateGroup_args> {
      public updateGroup() {
        super("updateGroup");
      }

      public updateGroup_args getEmptyArgsInstance() {
        return new updateGroup_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public updateGroup_result getResult(I iface, updateGroup_args args) throws org.apache.thrift.TException {
        updateGroup_result result = new updateGroup_result();
        try {
          result.success = iface.updateGroup(args.group);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class isGroupExists<I extends Iface> extends org.apache.thrift.ProcessFunction<I, isGroupExists_args> {
      public isGroupExists() {
        super("isGroupExists");
      }

      public isGroupExists_args getEmptyArgsInstance() {
        return new isGroupExists_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public isGroupExists_result getResult(I iface, isGroupExists_args args) throws org.apache.thrift.TException {
        isGroupExists_result result = new isGroupExists_result();
        try {
          result.success = iface.isGroupExists(args.domainId, args.groupId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class deleteGroup<I extends Iface> extends org.apache.thrift.ProcessFunction<I, deleteGroup_args> {
      public deleteGroup() {
        super("deleteGroup");
      }

      public deleteGroup_args getEmptyArgsInstance() {
        return new deleteGroup_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public deleteGroup_result getResult(I iface, deleteGroup_args args) throws org.apache.thrift.TException {
        deleteGroup_result result = new deleteGroup_result();
        try {
          result.success = iface.deleteGroup(args.domainId, args.groupId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getGroup<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getGroup_args> {
      public getGroup() {
        super("getGroup");
      }

      public getGroup_args getEmptyArgsInstance() {
        return new getGroup_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getGroup_result getResult(I iface, getGroup_args args) throws org.apache.thrift.TException {
        getGroup_result result = new getGroup_result();
        try {
          result.success = iface.getGroup(args.domainId, args.groupId);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getGroups<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getGroups_args> {
      public getGroups() {
        super("getGroups");
      }

      public getGroups_args getEmptyArgsInstance() {
        return new getGroups_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getGroups_result getResult(I iface, getGroups_args args) throws org.apache.thrift.TException {
        getGroups_result result = new getGroups_result();
        result.success = iface.getGroups(args.domainId, args.offset, args.limit);
        return result;
      }
    }

    public static class addUsersToGroup<I extends Iface> extends org.apache.thrift.ProcessFunction<I, addUsersToGroup_args> {
      public addUsersToGroup() {
        super("addUsersToGroup");
      }

      public addUsersToGroup_args getEmptyArgsInstance() {
        return new addUsersToGroup_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public addUsersToGroup_result getResult(I iface, addUsersToGroup_args args) throws org.apache.thrift.TException {
        addUsersToGroup_result result = new addUsersToGroup_result();
        try {
          result.success = iface.addUsersToGroup(args.domainId, args.userIds, args.groupId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class removeUsersFromGroup<I extends Iface> extends org.apache.thrift.ProcessFunction<I, removeUsersFromGroup_args> {
      public removeUsersFromGroup() {
        super("removeUsersFromGroup");
      }

      public removeUsersFromGroup_args getEmptyArgsInstance() {
        return new removeUsersFromGroup_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public removeUsersFromGroup_result getResult(I iface, removeUsersFromGroup_args args) throws org.apache.thrift.TException {
        removeUsersFromGroup_result result = new removeUsersFromGroup_result();
        try {
          result.success = iface.removeUsersFromGroup(args.domainId, args.userIds, args.groupId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getGroupMembersOfTypeUser<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getGroupMembersOfTypeUser_args> {
      public getGroupMembersOfTypeUser() {
        super("getGroupMembersOfTypeUser");
      }

      public getGroupMembersOfTypeUser_args getEmptyArgsInstance() {
        return new getGroupMembersOfTypeUser_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getGroupMembersOfTypeUser_result getResult(I iface, getGroupMembersOfTypeUser_args args) throws org.apache.thrift.TException {
        getGroupMembersOfTypeUser_result result = new getGroupMembersOfTypeUser_result();
        try {
          result.success = iface.getGroupMembersOfTypeUser(args.domainId, args.groupId, args.offset, args.limit);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getGroupMembersOfTypeGroup<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getGroupMembersOfTypeGroup_args> {
      public getGroupMembersOfTypeGroup() {
        super("getGroupMembersOfTypeGroup");
      }

      public getGroupMembersOfTypeGroup_args getEmptyArgsInstance() {
        return new getGroupMembersOfTypeGroup_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getGroupMembersOfTypeGroup_result getResult(I iface, getGroupMembersOfTypeGroup_args args) throws org.apache.thrift.TException {
        getGroupMembersOfTypeGroup_result result = new getGroupMembersOfTypeGroup_result();
        try {
          result.success = iface.getGroupMembersOfTypeGroup(args.domainId, args.groupId, args.offset, args.limit);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class addChildGroupsToParentGroup<I extends Iface> extends org.apache.thrift.ProcessFunction<I, addChildGroupsToParentGroup_args> {
      public addChildGroupsToParentGroup() {
        super("addChildGroupsToParentGroup");
      }

      public addChildGroupsToParentGroup_args getEmptyArgsInstance() {
        return new addChildGroupsToParentGroup_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public addChildGroupsToParentGroup_result getResult(I iface, addChildGroupsToParentGroup_args args) throws org.apache.thrift.TException {
        addChildGroupsToParentGroup_result result = new addChildGroupsToParentGroup_result();
        try {
          result.success = iface.addChildGroupsToParentGroup(args.domainId, args.childIds, args.groupId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class removeChildGroupFromParentGroup<I extends Iface> extends org.apache.thrift.ProcessFunction<I, removeChildGroupFromParentGroup_args> {
      public removeChildGroupFromParentGroup() {
        super("removeChildGroupFromParentGroup");
      }

      public removeChildGroupFromParentGroup_args getEmptyArgsInstance() {
        return new removeChildGroupFromParentGroup_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public removeChildGroupFromParentGroup_result getResult(I iface, removeChildGroupFromParentGroup_args args) throws org.apache.thrift.TException {
        removeChildGroupFromParentGroup_result result = new removeChildGroupFromParentGroup_result();
        try {
          result.success = iface.removeChildGroupFromParentGroup(args.domainId, args.childId, args.groupId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getAllMemberGroupsForUser<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getAllMemberGroupsForUser_args> {
      public getAllMemberGroupsForUser() {
        super("getAllMemberGroupsForUser");
      }

      public getAllMemberGroupsForUser_args getEmptyArgsInstance() {
        return new getAllMemberGroupsForUser_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getAllMemberGroupsForUser_result getResult(I iface, getAllMemberGroupsForUser_args args) throws org.apache.thrift.TException {
        getAllMemberGroupsForUser_result result = new getAllMemberGroupsForUser_result();
        try {
          result.success = iface.getAllMemberGroupsForUser(args.domainId, args.userId);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class createEntityType<I extends Iface> extends org.apache.thrift.ProcessFunction<I, createEntityType_args> {
      public createEntityType() {
        super("createEntityType");
      }

      public createEntityType_args getEmptyArgsInstance() {
        return new createEntityType_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public createEntityType_result getResult(I iface, createEntityType_args args) throws org.apache.thrift.TException {
        createEntityType_result result = new createEntityType_result();
        try {
          result.success = iface.createEntityType(args.entityType);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        } catch (org.apache.airavata.sharing.registry.models.DuplicateEntryException dee) {
          result.dee = dee;
        }
        return result;
      }
    }

    public static class updateEntityType<I extends Iface> extends org.apache.thrift.ProcessFunction<I, updateEntityType_args> {
      public updateEntityType() {
        super("updateEntityType");
      }

      public updateEntityType_args getEmptyArgsInstance() {
        return new updateEntityType_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public updateEntityType_result getResult(I iface, updateEntityType_args args) throws org.apache.thrift.TException {
        updateEntityType_result result = new updateEntityType_result();
        try {
          result.success = iface.updateEntityType(args.entityType);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class isEntityTypeExists<I extends Iface> extends org.apache.thrift.ProcessFunction<I, isEntityTypeExists_args> {
      public isEntityTypeExists() {
        super("isEntityTypeExists");
      }

      public isEntityTypeExists_args getEmptyArgsInstance() {
        return new isEntityTypeExists_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public isEntityTypeExists_result getResult(I iface, isEntityTypeExists_args args) throws org.apache.thrift.TException {
        isEntityTypeExists_result result = new isEntityTypeExists_result();
        try {
          result.success = iface.isEntityTypeExists(args.domainId, args.entityTypeId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class deleteEntityType<I extends Iface> extends org.apache.thrift.ProcessFunction<I, deleteEntityType_args> {
      public deleteEntityType() {
        super("deleteEntityType");
      }

      public deleteEntityType_args getEmptyArgsInstance() {
        return new deleteEntityType_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public deleteEntityType_result getResult(I iface, deleteEntityType_args args) throws org.apache.thrift.TException {
        deleteEntityType_result result = new deleteEntityType_result();
        try {
          result.success = iface.deleteEntityType(args.domainId, args.entityTypeId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getEntityType<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getEntityType_args> {
      public getEntityType() {
        super("getEntityType");
      }

      public getEntityType_args getEmptyArgsInstance() {
        return new getEntityType_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getEntityType_result getResult(I iface, getEntityType_args args) throws org.apache.thrift.TException {
        getEntityType_result result = new getEntityType_result();
        try {
          result.success = iface.getEntityType(args.domainId, args.entityTypeId);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getEntityTypes<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getEntityTypes_args> {
      public getEntityTypes() {
        super("getEntityTypes");
      }

      public getEntityTypes_args getEmptyArgsInstance() {
        return new getEntityTypes_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getEntityTypes_result getResult(I iface, getEntityTypes_args args) throws org.apache.thrift.TException {
        getEntityTypes_result result = new getEntityTypes_result();
        try {
          result.success = iface.getEntityTypes(args.domainId, args.offset, args.limit);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class createEntity<I extends Iface> extends org.apache.thrift.ProcessFunction<I, createEntity_args> {
      public createEntity() {
        super("createEntity");
      }

      public createEntity_args getEmptyArgsInstance() {
        return new createEntity_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public createEntity_result getResult(I iface, createEntity_args args) throws org.apache.thrift.TException {
        createEntity_result result = new createEntity_result();
        try {
          result.success = iface.createEntity(args.entity);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class updateEntity<I extends Iface> extends org.apache.thrift.ProcessFunction<I, updateEntity_args> {
      public updateEntity() {
        super("updateEntity");
      }

      public updateEntity_args getEmptyArgsInstance() {
        return new updateEntity_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public updateEntity_result getResult(I iface, updateEntity_args args) throws org.apache.thrift.TException {
        updateEntity_result result = new updateEntity_result();
        try {
          result.success = iface.updateEntity(args.entity);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class isEntityExists<I extends Iface> extends org.apache.thrift.ProcessFunction<I, isEntityExists_args> {
      public isEntityExists() {
        super("isEntityExists");
      }

      public isEntityExists_args getEmptyArgsInstance() {
        return new isEntityExists_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public isEntityExists_result getResult(I iface, isEntityExists_args args) throws org.apache.thrift.TException {
        isEntityExists_result result = new isEntityExists_result();
        try {
          result.success = iface.isEntityExists(args.domainId, args.entityId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class deleteEntity<I extends Iface> extends org.apache.thrift.ProcessFunction<I, deleteEntity_args> {
      public deleteEntity() {
        super("deleteEntity");
      }

      public deleteEntity_args getEmptyArgsInstance() {
        return new deleteEntity_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public deleteEntity_result getResult(I iface, deleteEntity_args args) throws org.apache.thrift.TException {
        deleteEntity_result result = new deleteEntity_result();
        try {
          result.success = iface.deleteEntity(args.domainId, args.entityId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getEntity<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getEntity_args> {
      public getEntity() {
        super("getEntity");
      }

      public getEntity_args getEmptyArgsInstance() {
        return new getEntity_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getEntity_result getResult(I iface, getEntity_args args) throws org.apache.thrift.TException {
        getEntity_result result = new getEntity_result();
        try {
          result.success = iface.getEntity(args.domainId, args.entityId);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class searchEntities<I extends Iface> extends org.apache.thrift.ProcessFunction<I, searchEntities_args> {
      public searchEntities() {
        super("searchEntities");
      }

      public searchEntities_args getEmptyArgsInstance() {
        return new searchEntities_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public searchEntities_result getResult(I iface, searchEntities_args args) throws org.apache.thrift.TException {
        searchEntities_result result = new searchEntities_result();
        try {
          result.success = iface.searchEntities(args.domainId, args.userId, args.filters, args.offset, args.limit);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getListOfSharedUsers<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getListOfSharedUsers_args> {
      public getListOfSharedUsers() {
        super("getListOfSharedUsers");
      }

      public getListOfSharedUsers_args getEmptyArgsInstance() {
        return new getListOfSharedUsers_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getListOfSharedUsers_result getResult(I iface, getListOfSharedUsers_args args) throws org.apache.thrift.TException {
        getListOfSharedUsers_result result = new getListOfSharedUsers_result();
        try {
          result.success = iface.getListOfSharedUsers(args.domainId, args.entityId, args.permissionTypeId);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getListOfSharedGroups<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getListOfSharedGroups_args> {
      public getListOfSharedGroups() {
        super("getListOfSharedGroups");
      }

      public getListOfSharedGroups_args getEmptyArgsInstance() {
        return new getListOfSharedGroups_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getListOfSharedGroups_result getResult(I iface, getListOfSharedGroups_args args) throws org.apache.thrift.TException {
        getListOfSharedGroups_result result = new getListOfSharedGroups_result();
        try {
          result.success = iface.getListOfSharedGroups(args.domainId, args.entityId, args.permissionTypeId);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class createPermissionType<I extends Iface> extends org.apache.thrift.ProcessFunction<I, createPermissionType_args> {
      public createPermissionType() {
        super("createPermissionType");
      }

      public createPermissionType_args getEmptyArgsInstance() {
        return new createPermissionType_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public createPermissionType_result getResult(I iface, createPermissionType_args args) throws org.apache.thrift.TException {
        createPermissionType_result result = new createPermissionType_result();
        try {
          result.success = iface.createPermissionType(args.permissionType);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        } catch (org.apache.airavata.sharing.registry.models.DuplicateEntryException dee) {
          result.dee = dee;
        }
        return result;
      }
    }

    public static class updatePermissionType<I extends Iface> extends org.apache.thrift.ProcessFunction<I, updatePermissionType_args> {
      public updatePermissionType() {
        super("updatePermissionType");
      }

      public updatePermissionType_args getEmptyArgsInstance() {
        return new updatePermissionType_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public updatePermissionType_result getResult(I iface, updatePermissionType_args args) throws org.apache.thrift.TException {
        updatePermissionType_result result = new updatePermissionType_result();
        try {
          result.success = iface.updatePermissionType(args.permissionType);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class isPermissionExists<I extends Iface> extends org.apache.thrift.ProcessFunction<I, isPermissionExists_args> {
      public isPermissionExists() {
        super("isPermissionExists");
      }

      public isPermissionExists_args getEmptyArgsInstance() {
        return new isPermissionExists_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public isPermissionExists_result getResult(I iface, isPermissionExists_args args) throws org.apache.thrift.TException {
        isPermissionExists_result result = new isPermissionExists_result();
        try {
          result.success = iface.isPermissionExists(args.dimainId, args.permissionId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class deletePermissionType<I extends Iface> extends org.apache.thrift.ProcessFunction<I, deletePermissionType_args> {
      public deletePermissionType() {
        super("deletePermissionType");
      }

      public deletePermissionType_args getEmptyArgsInstance() {
        return new deletePermissionType_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public deletePermissionType_result getResult(I iface, deletePermissionType_args args) throws org.apache.thrift.TException {
        deletePermissionType_result result = new deletePermissionType_result();
        try {
          result.success = iface.deletePermissionType(args.domainId, args.permissionTypeId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getPermissionType<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getPermissionType_args> {
      public getPermissionType() {
        super("getPermissionType");
      }

      public getPermissionType_args getEmptyArgsInstance() {
        return new getPermissionType_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getPermissionType_result getResult(I iface, getPermissionType_args args) throws org.apache.thrift.TException {
        getPermissionType_result result = new getPermissionType_result();
        try {
          result.success = iface.getPermissionType(args.domainId, args.permissionTypeId);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class getPermissionTypes<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getPermissionTypes_args> {
      public getPermissionTypes() {
        super("getPermissionTypes");
      }

      public getPermissionTypes_args getEmptyArgsInstance() {
        return new getPermissionTypes_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public getPermissionTypes_result getResult(I iface, getPermissionTypes_args args) throws org.apache.thrift.TException {
        getPermissionTypes_result result = new getPermissionTypes_result();
        try {
          result.success = iface.getPermissionTypes(args.domainId, args.offset, args.limit);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class shareEntityWithUsers<I extends Iface> extends org.apache.thrift.ProcessFunction<I, shareEntityWithUsers_args> {
      public shareEntityWithUsers() {
        super("shareEntityWithUsers");
      }

      public shareEntityWithUsers_args getEmptyArgsInstance() {
        return new shareEntityWithUsers_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public shareEntityWithUsers_result getResult(I iface, shareEntityWithUsers_args args) throws org.apache.thrift.TException {
        shareEntityWithUsers_result result = new shareEntityWithUsers_result();
        try {
          result.success = iface.shareEntityWithUsers(args.domainId, args.entityId, args.userList, args.perssionTypeId, args.cascadePermission);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class revokeEntitySharingFromUsers<I extends Iface> extends org.apache.thrift.ProcessFunction<I, revokeEntitySharingFromUsers_args> {
      public revokeEntitySharingFromUsers() {
        super("revokeEntitySharingFromUsers");
      }

      public revokeEntitySharingFromUsers_args getEmptyArgsInstance() {
        return new revokeEntitySharingFromUsers_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public revokeEntitySharingFromUsers_result getResult(I iface, revokeEntitySharingFromUsers_args args) throws org.apache.thrift.TException {
        revokeEntitySharingFromUsers_result result = new revokeEntitySharingFromUsers_result();
        try {
          result.success = iface.revokeEntitySharingFromUsers(args.domainId, args.entityId, args.userList, args.perssionTypeId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class shareEntityWithGroups<I extends Iface> extends org.apache.thrift.ProcessFunction<I, shareEntityWithGroups_args> {
      public shareEntityWithGroups() {
        super("shareEntityWithGroups");
      }

      public shareEntityWithGroups_args getEmptyArgsInstance() {
        return new shareEntityWithGroups_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public shareEntityWithGroups_result getResult(I iface, shareEntityWithGroups_args args) throws org.apache.thrift.TException {
        shareEntityWithGroups_result result = new shareEntityWithGroups_result();
        try {
          result.success = iface.shareEntityWithGroups(args.domainId, args.entityId, args.groupList, args.perssionTypeId, args.cascadePermission);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class revokeEntitySharingFromGroups<I extends Iface> extends org.apache.thrift.ProcessFunction<I, revokeEntitySharingFromGroups_args> {
      public revokeEntitySharingFromGroups() {
        super("revokeEntitySharingFromGroups");
      }

      public revokeEntitySharingFromGroups_args getEmptyArgsInstance() {
        return new revokeEntitySharingFromGroups_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public revokeEntitySharingFromGroups_result getResult(I iface, revokeEntitySharingFromGroups_args args) throws org.apache.thrift.TException {
        revokeEntitySharingFromGroups_result result = new revokeEntitySharingFromGroups_result();
        try {
          result.success = iface.revokeEntitySharingFromGroups(args.domainId, args.entityId, args.groupList, args.perssionTypeId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

    public static class userHasAccess<I extends Iface> extends org.apache.thrift.ProcessFunction<I, userHasAccess_args> {
      public userHasAccess() {
        super("userHasAccess");
      }

      public userHasAccess_args getEmptyArgsInstance() {
        return new userHasAccess_args();
      }

      protected boolean isOneway() {
        return false;
      }

      public userHasAccess_result getResult(I iface, userHasAccess_args args) throws org.apache.thrift.TException {
        userHasAccess_result result = new userHasAccess_result();
        try {
          result.success = iface.userHasAccess(args.domainId, args.userId, args.entityId, args.permissionTypeId);
          result.setSuccessIsSet(true);
        } catch (org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
          result.sre = sre;
        }
        return result;
      }
    }

  }

  public static class AsyncProcessor<I extends AsyncIface> extends org.apache.thrift.TBaseAsyncProcessor<I> {
    private static final Logger LOGGER = LoggerFactory.getLogger(AsyncProcessor.class.getName());
    public AsyncProcessor(I iface) {
      super(iface, getProcessMap(new HashMap<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>>()));
    }

    protected AsyncProcessor(I iface, Map<String,  org.apache.thrift.AsyncProcessFunction<I, ? extends  org.apache.thrift.TBase, ?>> processMap) {
      super(iface, getProcessMap(processMap));
    }

    private static <I extends AsyncIface> Map<String,  org.apache.thrift.AsyncProcessFunction<I, ? extends  org.apache.thrift.TBase,?>> getProcessMap(Map<String,  org.apache.thrift.AsyncProcessFunction<I, ? extends  org.apache.thrift.TBase, ?>> processMap) {
      processMap.put("createDomain", new createDomain());
      processMap.put("updateDomain", new updateDomain());
      processMap.put("isDomainExists", new isDomainExists());
      processMap.put("deleteDomain", new deleteDomain());
      processMap.put("getDomain", new getDomain());
      processMap.put("getDomains", new getDomains());
      processMap.put("createUser", new createUser());
      processMap.put("updatedUser", new updatedUser());
      processMap.put("isUserExists", new isUserExists());
      processMap.put("deleteUser", new deleteUser());
      processMap.put("getUser", new getUser());
      processMap.put("getUsers", new getUsers());
      processMap.put("createGroup", new createGroup());
      processMap.put("updateGroup", new updateGroup());
      processMap.put("isGroupExists", new isGroupExists());
      processMap.put("deleteGroup", new deleteGroup());
      processMap.put("getGroup", new getGroup());
      processMap.put("getGroups", new getGroups());
      processMap.put("addUsersToGroup", new addUsersToGroup());
      processMap.put("removeUsersFromGroup", new removeUsersFromGroup());
      processMap.put("getGroupMembersOfTypeUser", new getGroupMembersOfTypeUser());
      processMap.put("getGroupMembersOfTypeGroup", new getGroupMembersOfTypeGroup());
      processMap.put("addChildGroupsToParentGroup", new addChildGroupsToParentGroup());
      processMap.put("removeChildGroupFromParentGroup", new removeChildGroupFromParentGroup());
      processMap.put("getAllMemberGroupsForUser", new getAllMemberGroupsForUser());
      processMap.put("createEntityType", new createEntityType());
      processMap.put("updateEntityType", new updateEntityType());
      processMap.put("isEntityTypeExists", new isEntityTypeExists());
      processMap.put("deleteEntityType", new deleteEntityType());
      processMap.put("getEntityType", new getEntityType());
      processMap.put("getEntityTypes", new getEntityTypes());
      processMap.put("createEntity", new createEntity());
      processMap.put("updateEntity", new updateEntity());
      processMap.put("isEntityExists", new isEntityExists());
      processMap.put("deleteEntity", new deleteEntity());
      processMap.put("getEntity", new getEntity());
      processMap.put("searchEntities", new searchEntities());
      processMap.put("getListOfSharedUsers", new getListOfSharedUsers());
      processMap.put("getListOfSharedGroups", new getListOfSharedGroups());
      processMap.put("createPermissionType", new createPermissionType());
      processMap.put("updatePermissionType", new updatePermissionType());
      processMap.put("isPermissionExists", new isPermissionExists());
      processMap.put("deletePermissionType", new deletePermissionType());
      processMap.put("getPermissionType", new getPermissionType());
      processMap.put("getPermissionTypes", new getPermissionTypes());
      processMap.put("shareEntityWithUsers", new shareEntityWithUsers());
      processMap.put("revokeEntitySharingFromUsers", new revokeEntitySharingFromUsers());
      processMap.put("shareEntityWithGroups", new shareEntityWithGroups());
      processMap.put("revokeEntitySharingFromGroups", new revokeEntitySharingFromGroups());
      processMap.put("userHasAccess", new userHasAccess());
      return processMap;
    }

    public static class createDomain<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, createDomain_args, String> {
      public createDomain() {
        super("createDomain");
      }

      public createDomain_args getEmptyArgsInstance() {
        return new createDomain_args();
      }

      public AsyncMethodCallback<String> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<String>() { 
          public void onComplete(String o) {
            createDomain_result result = new createDomain_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            createDomain_result result = new createDomain_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
            else             if (e instanceof org.apache.airavata.sharing.registry.models.DuplicateEntryException) {
                        result.dee = (org.apache.airavata.sharing.registry.models.DuplicateEntryException) e;
                        result.setDeeIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, createDomain_args args, org.apache.thrift.async.AsyncMethodCallback<String> resultHandler) throws TException {
        iface.createDomain(args.domain,resultHandler);
      }
    }

    public static class updateDomain<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, updateDomain_args, Boolean> {
      public updateDomain() {
        super("updateDomain");
      }

      public updateDomain_args getEmptyArgsInstance() {
        return new updateDomain_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            updateDomain_result result = new updateDomain_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            updateDomain_result result = new updateDomain_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, updateDomain_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.updateDomain(args.domain,resultHandler);
      }
    }

    public static class isDomainExists<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, isDomainExists_args, Boolean> {
      public isDomainExists() {
        super("isDomainExists");
      }

      public isDomainExists_args getEmptyArgsInstance() {
        return new isDomainExists_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            isDomainExists_result result = new isDomainExists_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            isDomainExists_result result = new isDomainExists_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, isDomainExists_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.isDomainExists(args.domainId,resultHandler);
      }
    }

    public static class deleteDomain<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, deleteDomain_args, Boolean> {
      public deleteDomain() {
        super("deleteDomain");
      }

      public deleteDomain_args getEmptyArgsInstance() {
        return new deleteDomain_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            deleteDomain_result result = new deleteDomain_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            deleteDomain_result result = new deleteDomain_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, deleteDomain_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.deleteDomain(args.domainId,resultHandler);
      }
    }

    public static class getDomain<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getDomain_args, org.apache.airavata.sharing.registry.models.Domain> {
      public getDomain() {
        super("getDomain");
      }

      public getDomain_args getEmptyArgsInstance() {
        return new getDomain_args();
      }

      public AsyncMethodCallback<org.apache.airavata.sharing.registry.models.Domain> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<org.apache.airavata.sharing.registry.models.Domain>() { 
          public void onComplete(org.apache.airavata.sharing.registry.models.Domain o) {
            getDomain_result result = new getDomain_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getDomain_result result = new getDomain_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getDomain_args args, org.apache.thrift.async.AsyncMethodCallback<org.apache.airavata.sharing.registry.models.Domain> resultHandler) throws TException {
        iface.getDomain(args.domainId,resultHandler);
      }
    }

    public static class getDomains<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getDomains_args, List<org.apache.airavata.sharing.registry.models.Domain>> {
      public getDomains() {
        super("getDomains");
      }

      public getDomains_args getEmptyArgsInstance() {
        return new getDomains_args();
      }

      public AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.Domain>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.Domain>>() { 
          public void onComplete(List<org.apache.airavata.sharing.registry.models.Domain> o) {
            getDomains_result result = new getDomains_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getDomains_result result = new getDomains_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getDomains_args args, org.apache.thrift.async.AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.Domain>> resultHandler) throws TException {
        iface.getDomains(args.offset, args.limit,resultHandler);
      }
    }

    public static class createUser<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, createUser_args, String> {
      public createUser() {
        super("createUser");
      }

      public createUser_args getEmptyArgsInstance() {
        return new createUser_args();
      }

      public AsyncMethodCallback<String> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<String>() { 
          public void onComplete(String o) {
            createUser_result result = new createUser_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            createUser_result result = new createUser_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
            else             if (e instanceof org.apache.airavata.sharing.registry.models.DuplicateEntryException) {
                        result.dee = (org.apache.airavata.sharing.registry.models.DuplicateEntryException) e;
                        result.setDeeIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, createUser_args args, org.apache.thrift.async.AsyncMethodCallback<String> resultHandler) throws TException {
        iface.createUser(args.user,resultHandler);
      }
    }

    public static class updatedUser<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, updatedUser_args, Boolean> {
      public updatedUser() {
        super("updatedUser");
      }

      public updatedUser_args getEmptyArgsInstance() {
        return new updatedUser_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            updatedUser_result result = new updatedUser_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            updatedUser_result result = new updatedUser_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, updatedUser_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.updatedUser(args.user,resultHandler);
      }
    }

    public static class isUserExists<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, isUserExists_args, Boolean> {
      public isUserExists() {
        super("isUserExists");
      }

      public isUserExists_args getEmptyArgsInstance() {
        return new isUserExists_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            isUserExists_result result = new isUserExists_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            isUserExists_result result = new isUserExists_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, isUserExists_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.isUserExists(args.domainId, args.userId,resultHandler);
      }
    }

    public static class deleteUser<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, deleteUser_args, Boolean> {
      public deleteUser() {
        super("deleteUser");
      }

      public deleteUser_args getEmptyArgsInstance() {
        return new deleteUser_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            deleteUser_result result = new deleteUser_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            deleteUser_result result = new deleteUser_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, deleteUser_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.deleteUser(args.domainId, args.userId,resultHandler);
      }
    }

    public static class getUser<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getUser_args, org.apache.airavata.sharing.registry.models.User> {
      public getUser() {
        super("getUser");
      }

      public getUser_args getEmptyArgsInstance() {
        return new getUser_args();
      }

      public AsyncMethodCallback<org.apache.airavata.sharing.registry.models.User> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<org.apache.airavata.sharing.registry.models.User>() { 
          public void onComplete(org.apache.airavata.sharing.registry.models.User o) {
            getUser_result result = new getUser_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getUser_result result = new getUser_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getUser_args args, org.apache.thrift.async.AsyncMethodCallback<org.apache.airavata.sharing.registry.models.User> resultHandler) throws TException {
        iface.getUser(args.domainId, args.userId,resultHandler);
      }
    }

    public static class getUsers<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getUsers_args, List<org.apache.airavata.sharing.registry.models.User>> {
      public getUsers() {
        super("getUsers");
      }

      public getUsers_args getEmptyArgsInstance() {
        return new getUsers_args();
      }

      public AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.User>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.User>>() { 
          public void onComplete(List<org.apache.airavata.sharing.registry.models.User> o) {
            getUsers_result result = new getUsers_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getUsers_result result = new getUsers_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getUsers_args args, org.apache.thrift.async.AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.User>> resultHandler) throws TException {
        iface.getUsers(args.domainId, args.offset, args.limit,resultHandler);
      }
    }

    public static class createGroup<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, createGroup_args, String> {
      public createGroup() {
        super("createGroup");
      }

      public createGroup_args getEmptyArgsInstance() {
        return new createGroup_args();
      }

      public AsyncMethodCallback<String> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<String>() { 
          public void onComplete(String o) {
            createGroup_result result = new createGroup_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            createGroup_result result = new createGroup_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, createGroup_args args, org.apache.thrift.async.AsyncMethodCallback<String> resultHandler) throws TException {
        iface.createGroup(args.group,resultHandler);
      }
    }

    public static class updateGroup<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, updateGroup_args, Boolean> {
      public updateGroup() {
        super("updateGroup");
      }

      public updateGroup_args getEmptyArgsInstance() {
        return new updateGroup_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            updateGroup_result result = new updateGroup_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            updateGroup_result result = new updateGroup_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, updateGroup_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.updateGroup(args.group,resultHandler);
      }
    }

    public static class isGroupExists<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, isGroupExists_args, Boolean> {
      public isGroupExists() {
        super("isGroupExists");
      }

      public isGroupExists_args getEmptyArgsInstance() {
        return new isGroupExists_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            isGroupExists_result result = new isGroupExists_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            isGroupExists_result result = new isGroupExists_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, isGroupExists_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.isGroupExists(args.domainId, args.groupId,resultHandler);
      }
    }

    public static class deleteGroup<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, deleteGroup_args, Boolean> {
      public deleteGroup() {
        super("deleteGroup");
      }

      public deleteGroup_args getEmptyArgsInstance() {
        return new deleteGroup_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            deleteGroup_result result = new deleteGroup_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            deleteGroup_result result = new deleteGroup_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, deleteGroup_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.deleteGroup(args.domainId, args.groupId,resultHandler);
      }
    }

    public static class getGroup<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getGroup_args, org.apache.airavata.sharing.registry.models.UserGroup> {
      public getGroup() {
        super("getGroup");
      }

      public getGroup_args getEmptyArgsInstance() {
        return new getGroup_args();
      }

      public AsyncMethodCallback<org.apache.airavata.sharing.registry.models.UserGroup> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<org.apache.airavata.sharing.registry.models.UserGroup>() { 
          public void onComplete(org.apache.airavata.sharing.registry.models.UserGroup o) {
            getGroup_result result = new getGroup_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getGroup_result result = new getGroup_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getGroup_args args, org.apache.thrift.async.AsyncMethodCallback<org.apache.airavata.sharing.registry.models.UserGroup> resultHandler) throws TException {
        iface.getGroup(args.domainId, args.groupId,resultHandler);
      }
    }

    public static class getGroups<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getGroups_args, List<org.apache.airavata.sharing.registry.models.UserGroup>> {
      public getGroups() {
        super("getGroups");
      }

      public getGroups_args getEmptyArgsInstance() {
        return new getGroups_args();
      }

      public AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.UserGroup>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.UserGroup>>() { 
          public void onComplete(List<org.apache.airavata.sharing.registry.models.UserGroup> o) {
            getGroups_result result = new getGroups_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getGroups_result result = new getGroups_result();
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getGroups_args args, org.apache.thrift.async.AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.UserGroup>> resultHandler) throws TException {
        iface.getGroups(args.domainId, args.offset, args.limit,resultHandler);
      }
    }

    public static class addUsersToGroup<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, addUsersToGroup_args, Boolean> {
      public addUsersToGroup() {
        super("addUsersToGroup");
      }

      public addUsersToGroup_args getEmptyArgsInstance() {
        return new addUsersToGroup_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            addUsersToGroup_result result = new addUsersToGroup_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            addUsersToGroup_result result = new addUsersToGroup_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, addUsersToGroup_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.addUsersToGroup(args.domainId, args.userIds, args.groupId,resultHandler);
      }
    }

    public static class removeUsersFromGroup<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, removeUsersFromGroup_args, Boolean> {
      public removeUsersFromGroup() {
        super("removeUsersFromGroup");
      }

      public removeUsersFromGroup_args getEmptyArgsInstance() {
        return new removeUsersFromGroup_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            removeUsersFromGroup_result result = new removeUsersFromGroup_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            removeUsersFromGroup_result result = new removeUsersFromGroup_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, removeUsersFromGroup_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.removeUsersFromGroup(args.domainId, args.userIds, args.groupId,resultHandler);
      }
    }

    public static class getGroupMembersOfTypeUser<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getGroupMembersOfTypeUser_args, List<org.apache.airavata.sharing.registry.models.User>> {
      public getGroupMembersOfTypeUser() {
        super("getGroupMembersOfTypeUser");
      }

      public getGroupMembersOfTypeUser_args getEmptyArgsInstance() {
        return new getGroupMembersOfTypeUser_args();
      }

      public AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.User>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.User>>() { 
          public void onComplete(List<org.apache.airavata.sharing.registry.models.User> o) {
            getGroupMembersOfTypeUser_result result = new getGroupMembersOfTypeUser_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getGroupMembersOfTypeUser_result result = new getGroupMembersOfTypeUser_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getGroupMembersOfTypeUser_args args, org.apache.thrift.async.AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.User>> resultHandler) throws TException {
        iface.getGroupMembersOfTypeUser(args.domainId, args.groupId, args.offset, args.limit,resultHandler);
      }
    }

    public static class getGroupMembersOfTypeGroup<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getGroupMembersOfTypeGroup_args, List<org.apache.airavata.sharing.registry.models.UserGroup>> {
      public getGroupMembersOfTypeGroup() {
        super("getGroupMembersOfTypeGroup");
      }

      public getGroupMembersOfTypeGroup_args getEmptyArgsInstance() {
        return new getGroupMembersOfTypeGroup_args();
      }

      public AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.UserGroup>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.UserGroup>>() { 
          public void onComplete(List<org.apache.airavata.sharing.registry.models.UserGroup> o) {
            getGroupMembersOfTypeGroup_result result = new getGroupMembersOfTypeGroup_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getGroupMembersOfTypeGroup_result result = new getGroupMembersOfTypeGroup_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getGroupMembersOfTypeGroup_args args, org.apache.thrift.async.AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.UserGroup>> resultHandler) throws TException {
        iface.getGroupMembersOfTypeGroup(args.domainId, args.groupId, args.offset, args.limit,resultHandler);
      }
    }

    public static class addChildGroupsToParentGroup<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, addChildGroupsToParentGroup_args, Boolean> {
      public addChildGroupsToParentGroup() {
        super("addChildGroupsToParentGroup");
      }

      public addChildGroupsToParentGroup_args getEmptyArgsInstance() {
        return new addChildGroupsToParentGroup_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            addChildGroupsToParentGroup_result result = new addChildGroupsToParentGroup_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            addChildGroupsToParentGroup_result result = new addChildGroupsToParentGroup_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, addChildGroupsToParentGroup_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.addChildGroupsToParentGroup(args.domainId, args.childIds, args.groupId,resultHandler);
      }
    }

    public static class removeChildGroupFromParentGroup<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, removeChildGroupFromParentGroup_args, Boolean> {
      public removeChildGroupFromParentGroup() {
        super("removeChildGroupFromParentGroup");
      }

      public removeChildGroupFromParentGroup_args getEmptyArgsInstance() {
        return new removeChildGroupFromParentGroup_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            removeChildGroupFromParentGroup_result result = new removeChildGroupFromParentGroup_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            removeChildGroupFromParentGroup_result result = new removeChildGroupFromParentGroup_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, removeChildGroupFromParentGroup_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.removeChildGroupFromParentGroup(args.domainId, args.childId, args.groupId,resultHandler);
      }
    }

    public static class getAllMemberGroupsForUser<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getAllMemberGroupsForUser_args, List<org.apache.airavata.sharing.registry.models.UserGroup>> {
      public getAllMemberGroupsForUser() {
        super("getAllMemberGroupsForUser");
      }

      public getAllMemberGroupsForUser_args getEmptyArgsInstance() {
        return new getAllMemberGroupsForUser_args();
      }

      public AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.UserGroup>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.UserGroup>>() { 
          public void onComplete(List<org.apache.airavata.sharing.registry.models.UserGroup> o) {
            getAllMemberGroupsForUser_result result = new getAllMemberGroupsForUser_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getAllMemberGroupsForUser_result result = new getAllMemberGroupsForUser_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getAllMemberGroupsForUser_args args, org.apache.thrift.async.AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.UserGroup>> resultHandler) throws TException {
        iface.getAllMemberGroupsForUser(args.domainId, args.userId,resultHandler);
      }
    }

    public static class createEntityType<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, createEntityType_args, String> {
      public createEntityType() {
        super("createEntityType");
      }

      public createEntityType_args getEmptyArgsInstance() {
        return new createEntityType_args();
      }

      public AsyncMethodCallback<String> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<String>() { 
          public void onComplete(String o) {
            createEntityType_result result = new createEntityType_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            createEntityType_result result = new createEntityType_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
            else             if (e instanceof org.apache.airavata.sharing.registry.models.DuplicateEntryException) {
                        result.dee = (org.apache.airavata.sharing.registry.models.DuplicateEntryException) e;
                        result.setDeeIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, createEntityType_args args, org.apache.thrift.async.AsyncMethodCallback<String> resultHandler) throws TException {
        iface.createEntityType(args.entityType,resultHandler);
      }
    }

    public static class updateEntityType<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, updateEntityType_args, Boolean> {
      public updateEntityType() {
        super("updateEntityType");
      }

      public updateEntityType_args getEmptyArgsInstance() {
        return new updateEntityType_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            updateEntityType_result result = new updateEntityType_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            updateEntityType_result result = new updateEntityType_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, updateEntityType_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.updateEntityType(args.entityType,resultHandler);
      }
    }

    public static class isEntityTypeExists<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, isEntityTypeExists_args, Boolean> {
      public isEntityTypeExists() {
        super("isEntityTypeExists");
      }

      public isEntityTypeExists_args getEmptyArgsInstance() {
        return new isEntityTypeExists_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            isEntityTypeExists_result result = new isEntityTypeExists_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            isEntityTypeExists_result result = new isEntityTypeExists_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, isEntityTypeExists_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.isEntityTypeExists(args.domainId, args.entityTypeId,resultHandler);
      }
    }

    public static class deleteEntityType<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, deleteEntityType_args, Boolean> {
      public deleteEntityType() {
        super("deleteEntityType");
      }

      public deleteEntityType_args getEmptyArgsInstance() {
        return new deleteEntityType_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            deleteEntityType_result result = new deleteEntityType_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            deleteEntityType_result result = new deleteEntityType_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, deleteEntityType_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.deleteEntityType(args.domainId, args.entityTypeId,resultHandler);
      }
    }

    public static class getEntityType<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getEntityType_args, org.apache.airavata.sharing.registry.models.EntityType> {
      public getEntityType() {
        super("getEntityType");
      }

      public getEntityType_args getEmptyArgsInstance() {
        return new getEntityType_args();
      }

      public AsyncMethodCallback<org.apache.airavata.sharing.registry.models.EntityType> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<org.apache.airavata.sharing.registry.models.EntityType>() { 
          public void onComplete(org.apache.airavata.sharing.registry.models.EntityType o) {
            getEntityType_result result = new getEntityType_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getEntityType_result result = new getEntityType_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getEntityType_args args, org.apache.thrift.async.AsyncMethodCallback<org.apache.airavata.sharing.registry.models.EntityType> resultHandler) throws TException {
        iface.getEntityType(args.domainId, args.entityTypeId,resultHandler);
      }
    }

    public static class getEntityTypes<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getEntityTypes_args, List<org.apache.airavata.sharing.registry.models.EntityType>> {
      public getEntityTypes() {
        super("getEntityTypes");
      }

      public getEntityTypes_args getEmptyArgsInstance() {
        return new getEntityTypes_args();
      }

      public AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.EntityType>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.EntityType>>() { 
          public void onComplete(List<org.apache.airavata.sharing.registry.models.EntityType> o) {
            getEntityTypes_result result = new getEntityTypes_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getEntityTypes_result result = new getEntityTypes_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getEntityTypes_args args, org.apache.thrift.async.AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.EntityType>> resultHandler) throws TException {
        iface.getEntityTypes(args.domainId, args.offset, args.limit,resultHandler);
      }
    }

    public static class createEntity<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, createEntity_args, String> {
      public createEntity() {
        super("createEntity");
      }

      public createEntity_args getEmptyArgsInstance() {
        return new createEntity_args();
      }

      public AsyncMethodCallback<String> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<String>() { 
          public void onComplete(String o) {
            createEntity_result result = new createEntity_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            createEntity_result result = new createEntity_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, createEntity_args args, org.apache.thrift.async.AsyncMethodCallback<String> resultHandler) throws TException {
        iface.createEntity(args.entity,resultHandler);
      }
    }

    public static class updateEntity<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, updateEntity_args, Boolean> {
      public updateEntity() {
        super("updateEntity");
      }

      public updateEntity_args getEmptyArgsInstance() {
        return new updateEntity_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            updateEntity_result result = new updateEntity_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            updateEntity_result result = new updateEntity_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, updateEntity_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.updateEntity(args.entity,resultHandler);
      }
    }

    public static class isEntityExists<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, isEntityExists_args, Boolean> {
      public isEntityExists() {
        super("isEntityExists");
      }

      public isEntityExists_args getEmptyArgsInstance() {
        return new isEntityExists_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            isEntityExists_result result = new isEntityExists_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            isEntityExists_result result = new isEntityExists_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, isEntityExists_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.isEntityExists(args.domainId, args.entityId,resultHandler);
      }
    }

    public static class deleteEntity<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, deleteEntity_args, Boolean> {
      public deleteEntity() {
        super("deleteEntity");
      }

      public deleteEntity_args getEmptyArgsInstance() {
        return new deleteEntity_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            deleteEntity_result result = new deleteEntity_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            deleteEntity_result result = new deleteEntity_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, deleteEntity_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.deleteEntity(args.domainId, args.entityId,resultHandler);
      }
    }

    public static class getEntity<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getEntity_args, org.apache.airavata.sharing.registry.models.Entity> {
      public getEntity() {
        super("getEntity");
      }

      public getEntity_args getEmptyArgsInstance() {
        return new getEntity_args();
      }

      public AsyncMethodCallback<org.apache.airavata.sharing.registry.models.Entity> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<org.apache.airavata.sharing.registry.models.Entity>() { 
          public void onComplete(org.apache.airavata.sharing.registry.models.Entity o) {
            getEntity_result result = new getEntity_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getEntity_result result = new getEntity_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getEntity_args args, org.apache.thrift.async.AsyncMethodCallback<org.apache.airavata.sharing.registry.models.Entity> resultHandler) throws TException {
        iface.getEntity(args.domainId, args.entityId,resultHandler);
      }
    }

    public static class searchEntities<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, searchEntities_args, List<org.apache.airavata.sharing.registry.models.Entity>> {
      public searchEntities() {
        super("searchEntities");
      }

      public searchEntities_args getEmptyArgsInstance() {
        return new searchEntities_args();
      }

      public AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.Entity>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.Entity>>() { 
          public void onComplete(List<org.apache.airavata.sharing.registry.models.Entity> o) {
            searchEntities_result result = new searchEntities_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            searchEntities_result result = new searchEntities_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, searchEntities_args args, org.apache.thrift.async.AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.Entity>> resultHandler) throws TException {
        iface.searchEntities(args.domainId, args.userId, args.filters, args.offset, args.limit,resultHandler);
      }
    }

    public static class getListOfSharedUsers<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getListOfSharedUsers_args, List<org.apache.airavata.sharing.registry.models.User>> {
      public getListOfSharedUsers() {
        super("getListOfSharedUsers");
      }

      public getListOfSharedUsers_args getEmptyArgsInstance() {
        return new getListOfSharedUsers_args();
      }

      public AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.User>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.User>>() { 
          public void onComplete(List<org.apache.airavata.sharing.registry.models.User> o) {
            getListOfSharedUsers_result result = new getListOfSharedUsers_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getListOfSharedUsers_result result = new getListOfSharedUsers_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getListOfSharedUsers_args args, org.apache.thrift.async.AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.User>> resultHandler) throws TException {
        iface.getListOfSharedUsers(args.domainId, args.entityId, args.permissionTypeId,resultHandler);
      }
    }

    public static class getListOfSharedGroups<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getListOfSharedGroups_args, List<org.apache.airavata.sharing.registry.models.UserGroup>> {
      public getListOfSharedGroups() {
        super("getListOfSharedGroups");
      }

      public getListOfSharedGroups_args getEmptyArgsInstance() {
        return new getListOfSharedGroups_args();
      }

      public AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.UserGroup>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.UserGroup>>() { 
          public void onComplete(List<org.apache.airavata.sharing.registry.models.UserGroup> o) {
            getListOfSharedGroups_result result = new getListOfSharedGroups_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getListOfSharedGroups_result result = new getListOfSharedGroups_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getListOfSharedGroups_args args, org.apache.thrift.async.AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.UserGroup>> resultHandler) throws TException {
        iface.getListOfSharedGroups(args.domainId, args.entityId, args.permissionTypeId,resultHandler);
      }
    }

    public static class createPermissionType<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, createPermissionType_args, String> {
      public createPermissionType() {
        super("createPermissionType");
      }

      public createPermissionType_args getEmptyArgsInstance() {
        return new createPermissionType_args();
      }

      public AsyncMethodCallback<String> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<String>() { 
          public void onComplete(String o) {
            createPermissionType_result result = new createPermissionType_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            createPermissionType_result result = new createPermissionType_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
            else             if (e instanceof org.apache.airavata.sharing.registry.models.DuplicateEntryException) {
                        result.dee = (org.apache.airavata.sharing.registry.models.DuplicateEntryException) e;
                        result.setDeeIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, createPermissionType_args args, org.apache.thrift.async.AsyncMethodCallback<String> resultHandler) throws TException {
        iface.createPermissionType(args.permissionType,resultHandler);
      }
    }

    public static class updatePermissionType<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, updatePermissionType_args, Boolean> {
      public updatePermissionType() {
        super("updatePermissionType");
      }

      public updatePermissionType_args getEmptyArgsInstance() {
        return new updatePermissionType_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            updatePermissionType_result result = new updatePermissionType_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            updatePermissionType_result result = new updatePermissionType_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, updatePermissionType_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.updatePermissionType(args.permissionType,resultHandler);
      }
    }

    public static class isPermissionExists<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, isPermissionExists_args, Boolean> {
      public isPermissionExists() {
        super("isPermissionExists");
      }

      public isPermissionExists_args getEmptyArgsInstance() {
        return new isPermissionExists_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            isPermissionExists_result result = new isPermissionExists_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            isPermissionExists_result result = new isPermissionExists_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, isPermissionExists_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.isPermissionExists(args.dimainId, args.permissionId,resultHandler);
      }
    }

    public static class deletePermissionType<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, deletePermissionType_args, Boolean> {
      public deletePermissionType() {
        super("deletePermissionType");
      }

      public deletePermissionType_args getEmptyArgsInstance() {
        return new deletePermissionType_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            deletePermissionType_result result = new deletePermissionType_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            deletePermissionType_result result = new deletePermissionType_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, deletePermissionType_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.deletePermissionType(args.domainId, args.permissionTypeId,resultHandler);
      }
    }

    public static class getPermissionType<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getPermissionType_args, org.apache.airavata.sharing.registry.models.PermissionType> {
      public getPermissionType() {
        super("getPermissionType");
      }

      public getPermissionType_args getEmptyArgsInstance() {
        return new getPermissionType_args();
      }

      public AsyncMethodCallback<org.apache.airavata.sharing.registry.models.PermissionType> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<org.apache.airavata.sharing.registry.models.PermissionType>() { 
          public void onComplete(org.apache.airavata.sharing.registry.models.PermissionType o) {
            getPermissionType_result result = new getPermissionType_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getPermissionType_result result = new getPermissionType_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getPermissionType_args args, org.apache.thrift.async.AsyncMethodCallback<org.apache.airavata.sharing.registry.models.PermissionType> resultHandler) throws TException {
        iface.getPermissionType(args.domainId, args.permissionTypeId,resultHandler);
      }
    }

    public static class getPermissionTypes<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getPermissionTypes_args, List<org.apache.airavata.sharing.registry.models.PermissionType>> {
      public getPermissionTypes() {
        super("getPermissionTypes");
      }

      public getPermissionTypes_args getEmptyArgsInstance() {
        return new getPermissionTypes_args();
      }

      public AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.PermissionType>> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.PermissionType>>() { 
          public void onComplete(List<org.apache.airavata.sharing.registry.models.PermissionType> o) {
            getPermissionTypes_result result = new getPermissionTypes_result();
            result.success = o;
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            getPermissionTypes_result result = new getPermissionTypes_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, getPermissionTypes_args args, org.apache.thrift.async.AsyncMethodCallback<List<org.apache.airavata.sharing.registry.models.PermissionType>> resultHandler) throws TException {
        iface.getPermissionTypes(args.domainId, args.offset, args.limit,resultHandler);
      }
    }

    public static class shareEntityWithUsers<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, shareEntityWithUsers_args, Boolean> {
      public shareEntityWithUsers() {
        super("shareEntityWithUsers");
      }

      public shareEntityWithUsers_args getEmptyArgsInstance() {
        return new shareEntityWithUsers_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            shareEntityWithUsers_result result = new shareEntityWithUsers_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            shareEntityWithUsers_result result = new shareEntityWithUsers_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, shareEntityWithUsers_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.shareEntityWithUsers(args.domainId, args.entityId, args.userList, args.perssionTypeId, args.cascadePermission,resultHandler);
      }
    }

    public static class revokeEntitySharingFromUsers<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, revokeEntitySharingFromUsers_args, Boolean> {
      public revokeEntitySharingFromUsers() {
        super("revokeEntitySharingFromUsers");
      }

      public revokeEntitySharingFromUsers_args getEmptyArgsInstance() {
        return new revokeEntitySharingFromUsers_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            revokeEntitySharingFromUsers_result result = new revokeEntitySharingFromUsers_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            revokeEntitySharingFromUsers_result result = new revokeEntitySharingFromUsers_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, revokeEntitySharingFromUsers_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.revokeEntitySharingFromUsers(args.domainId, args.entityId, args.userList, args.perssionTypeId,resultHandler);
      }
    }

    public static class shareEntityWithGroups<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, shareEntityWithGroups_args, Boolean> {
      public shareEntityWithGroups() {
        super("shareEntityWithGroups");
      }

      public shareEntityWithGroups_args getEmptyArgsInstance() {
        return new shareEntityWithGroups_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            shareEntityWithGroups_result result = new shareEntityWithGroups_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            shareEntityWithGroups_result result = new shareEntityWithGroups_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, shareEntityWithGroups_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.shareEntityWithGroups(args.domainId, args.entityId, args.groupList, args.perssionTypeId, args.cascadePermission,resultHandler);
      }
    }

    public static class revokeEntitySharingFromGroups<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, revokeEntitySharingFromGroups_args, Boolean> {
      public revokeEntitySharingFromGroups() {
        super("revokeEntitySharingFromGroups");
      }

      public revokeEntitySharingFromGroups_args getEmptyArgsInstance() {
        return new revokeEntitySharingFromGroups_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            revokeEntitySharingFromGroups_result result = new revokeEntitySharingFromGroups_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            revokeEntitySharingFromGroups_result result = new revokeEntitySharingFromGroups_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, revokeEntitySharingFromGroups_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.revokeEntitySharingFromGroups(args.domainId, args.entityId, args.groupList, args.perssionTypeId,resultHandler);
      }
    }

    public static class userHasAccess<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, userHasAccess_args, Boolean> {
      public userHasAccess() {
        super("userHasAccess");
      }

      public userHasAccess_args getEmptyArgsInstance() {
        return new userHasAccess_args();
      }

      public AsyncMethodCallback<Boolean> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
        final org.apache.thrift.AsyncProcessFunction fcall = this;
        return new AsyncMethodCallback<Boolean>() { 
          public void onComplete(Boolean o) {
            userHasAccess_result result = new userHasAccess_result();
            result.success = o;
            result.setSuccessIsSet(true);
            try {
              fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
              return;
            } catch (Exception e) {
              LOGGER.error("Exception writing to internal frame buffer", e);
            }
            fb.close();
          }
          public void onError(Exception e) {
            byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
            org.apache.thrift.TBase msg;
            userHasAccess_result result = new userHasAccess_result();
            if (e instanceof org.apache.airavata.sharing.registry.models.SharingRegistryException) {
                        result.sre = (org.apache.airavata.sharing.registry.models.SharingRegistryException) e;
                        result.setSreIsSet(true);
                        msg = result;
            }
             else 
            {
              msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
              msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
            }
            try {
              fcall.sendResponse(fb,msg,msgType,seqid);
              return;
            } catch (Exception ex) {
              LOGGER.error("Exception writing to internal frame buffer", ex);
            }
            fb.close();
          }
        };
      }

      protected boolean isOneway() {
        return false;
      }

      public void start(I iface, userHasAccess_args args, org.apache.thrift.async.AsyncMethodCallback<Boolean> resultHandler) throws TException {
        iface.userHasAccess(args.domainId, args.userId, args.entityId, args.permissionTypeId,resultHandler);
      }
    }

  }

  public static class createDomain_args implements org.apache.thrift.TBase<createDomain_args, createDomain_args._Fields>, java.io.Serializable, Cloneable, Comparable<createDomain_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createDomain_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_FIELD_DESC = new org.apache.thrift.protocol.TField("domain", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new createDomain_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new createDomain_argsTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.Domain domain; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN((short)1, "domain");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN
            return DOMAIN;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN, new org.apache.thrift.meta_data.FieldMetaData("domain", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.Domain.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createDomain_args.class, metaDataMap);
    }

    public createDomain_args() {
    }

    public createDomain_args(
      org.apache.airavata.sharing.registry.models.Domain domain)
    {
      this();
      this.domain = domain;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public createDomain_args(createDomain_args other) {
      if (other.isSetDomain()) {
        this.domain = new org.apache.airavata.sharing.registry.models.Domain(other.domain);
      }
    }

    public createDomain_args deepCopy() {
      return new createDomain_args(this);
    }

    @Override
    public void clear() {
      this.domain = null;
    }

    public org.apache.airavata.sharing.registry.models.Domain getDomain() {
      return this.domain;
    }

    public createDomain_args setDomain(org.apache.airavata.sharing.registry.models.Domain domain) {
      this.domain = domain;
      return this;
    }

    public void unsetDomain() {
      this.domain = null;
    }

    /** Returns true if field domain is set (has been assigned a value) and false otherwise */
    public boolean isSetDomain() {
      return this.domain != null;
    }

    public void setDomainIsSet(boolean value) {
      if (!value) {
        this.domain = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN:
        if (value == null) {
          unsetDomain();
        } else {
          setDomain((org.apache.airavata.sharing.registry.models.Domain)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN:
        return getDomain();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN:
        return isSetDomain();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof createDomain_args)
        return this.equals((createDomain_args)that);
      return false;
    }

    public boolean equals(createDomain_args that) {
      if (that == null)
        return false;

      boolean this_present_domain = true && this.isSetDomain();
      boolean that_present_domain = true && that.isSetDomain();
      if (this_present_domain || that_present_domain) {
        if (!(this_present_domain && that_present_domain))
          return false;
        if (!this.domain.equals(that.domain))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domain = true && (isSetDomain());
      list.add(present_domain);
      if (present_domain)
        list.add(domain);

      return list.hashCode();
    }

    @Override
    public int compareTo(createDomain_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomain()).compareTo(other.isSetDomain());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomain()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domain, other.domain);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("createDomain_args(");
      boolean first = true;

      sb.append("domain:");
      if (this.domain == null) {
        sb.append("null");
      } else {
        sb.append(this.domain);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domain == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domain' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
      if (domain != null) {
        domain.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class createDomain_argsStandardSchemeFactory implements SchemeFactory {
      public createDomain_argsStandardScheme getScheme() {
        return new createDomain_argsStandardScheme();
      }
    }

    private static class createDomain_argsStandardScheme extends StandardScheme<createDomain_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, createDomain_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.domain = new org.apache.airavata.sharing.registry.models.Domain();
                struct.domain.read(iprot);
                struct.setDomainIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, createDomain_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domain != null) {
          oprot.writeFieldBegin(DOMAIN_FIELD_DESC);
          struct.domain.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class createDomain_argsTupleSchemeFactory implements SchemeFactory {
      public createDomain_argsTupleScheme getScheme() {
        return new createDomain_argsTupleScheme();
      }
    }

    private static class createDomain_argsTupleScheme extends TupleScheme<createDomain_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, createDomain_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        struct.domain.write(oprot);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, createDomain_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domain = new org.apache.airavata.sharing.registry.models.Domain();
        struct.domain.read(iprot);
        struct.setDomainIsSet(true);
      }
    }

  }

  public static class createDomain_result implements org.apache.thrift.TBase<createDomain_result, createDomain_result._Fields>, java.io.Serializable, Cloneable, Comparable<createDomain_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createDomain_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);
    private static final org.apache.thrift.protocol.TField DEE_FIELD_DESC = new org.apache.thrift.protocol.TField("dee", org.apache.thrift.protocol.TType.STRUCT, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new createDomain_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new createDomain_resultTupleSchemeFactory());
    }

    public String success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required
    public org.apache.airavata.sharing.registry.models.DuplicateEntryException dee; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre"),
      DEE((short)2, "dee");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          case 2: // DEE
            return DEE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      tmpMap.put(_Fields.DEE, new org.apache.thrift.meta_data.FieldMetaData("dee", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createDomain_result.class, metaDataMap);
    }

    public createDomain_result() {
    }

    public createDomain_result(
      String success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre,
      org.apache.airavata.sharing.registry.models.DuplicateEntryException dee)
    {
      this();
      this.success = success;
      this.sre = sre;
      this.dee = dee;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public createDomain_result(createDomain_result other) {
      if (other.isSetSuccess()) {
        this.success = other.success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
      if (other.isSetDee()) {
        this.dee = new org.apache.airavata.sharing.registry.models.DuplicateEntryException(other.dee);
      }
    }

    public createDomain_result deepCopy() {
      return new createDomain_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
      this.dee = null;
    }

    public String getSuccess() {
      return this.success;
    }

    public createDomain_result setSuccess(String success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public createDomain_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.DuplicateEntryException getDee() {
      return this.dee;
    }

    public createDomain_result setDee(org.apache.airavata.sharing.registry.models.DuplicateEntryException dee) {
      this.dee = dee;
      return this;
    }

    public void unsetDee() {
      this.dee = null;
    }

    /** Returns true if field dee is set (has been assigned a value) and false otherwise */
    public boolean isSetDee() {
      return this.dee != null;
    }

    public void setDeeIsSet(boolean value) {
      if (!value) {
        this.dee = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((String)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      case DEE:
        if (value == null) {
          unsetDee();
        } else {
          setDee((org.apache.airavata.sharing.registry.models.DuplicateEntryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      case DEE:
        return getDee();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      case DEE:
        return isSetDee();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof createDomain_result)
        return this.equals((createDomain_result)that);
      return false;
    }

    public boolean equals(createDomain_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      boolean this_present_dee = true && this.isSetDee();
      boolean that_present_dee = true && that.isSetDee();
      if (this_present_dee || that_present_dee) {
        if (!(this_present_dee && that_present_dee))
          return false;
        if (!this.dee.equals(that.dee))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      boolean present_dee = true && (isSetDee());
      list.add(present_dee);
      if (present_dee)
        list.add(dee);

      return list.hashCode();
    }

    @Override
    public int compareTo(createDomain_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetDee()).compareTo(other.isSetDee());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDee()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.dee, other.dee);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("createDomain_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("dee:");
      if (this.dee == null) {
        sb.append("null");
      } else {
        sb.append(this.dee);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class createDomain_resultStandardSchemeFactory implements SchemeFactory {
      public createDomain_resultStandardScheme getScheme() {
        return new createDomain_resultStandardScheme();
      }
    }

    private static class createDomain_resultStandardScheme extends StandardScheme<createDomain_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, createDomain_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.success = iprot.readString();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // DEE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.dee = new org.apache.airavata.sharing.registry.models.DuplicateEntryException();
                struct.dee.read(iprot);
                struct.setDeeIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, createDomain_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeString(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.dee != null) {
          oprot.writeFieldBegin(DEE_FIELD_DESC);
          struct.dee.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class createDomain_resultTupleSchemeFactory implements SchemeFactory {
      public createDomain_resultTupleScheme getScheme() {
        return new createDomain_resultTupleScheme();
      }
    }

    private static class createDomain_resultTupleScheme extends TupleScheme<createDomain_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, createDomain_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        if (struct.isSetDee()) {
          optionals.set(2);
        }
        oprot.writeBitSet(optionals, 3);
        if (struct.isSetSuccess()) {
          oprot.writeString(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
        if (struct.isSetDee()) {
          struct.dee.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, createDomain_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(3);
        if (incoming.get(0)) {
          struct.success = iprot.readString();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
        if (incoming.get(2)) {
          struct.dee = new org.apache.airavata.sharing.registry.models.DuplicateEntryException();
          struct.dee.read(iprot);
          struct.setDeeIsSet(true);
        }
      }
    }

  }

  public static class updateDomain_args implements org.apache.thrift.TBase<updateDomain_args, updateDomain_args._Fields>, java.io.Serializable, Cloneable, Comparable<updateDomain_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updateDomain_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_FIELD_DESC = new org.apache.thrift.protocol.TField("domain", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updateDomain_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updateDomain_argsTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.Domain domain; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN((short)1, "domain");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN
            return DOMAIN;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN, new org.apache.thrift.meta_data.FieldMetaData("domain", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.Domain.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updateDomain_args.class, metaDataMap);
    }

    public updateDomain_args() {
    }

    public updateDomain_args(
      org.apache.airavata.sharing.registry.models.Domain domain)
    {
      this();
      this.domain = domain;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updateDomain_args(updateDomain_args other) {
      if (other.isSetDomain()) {
        this.domain = new org.apache.airavata.sharing.registry.models.Domain(other.domain);
      }
    }

    public updateDomain_args deepCopy() {
      return new updateDomain_args(this);
    }

    @Override
    public void clear() {
      this.domain = null;
    }

    public org.apache.airavata.sharing.registry.models.Domain getDomain() {
      return this.domain;
    }

    public updateDomain_args setDomain(org.apache.airavata.sharing.registry.models.Domain domain) {
      this.domain = domain;
      return this;
    }

    public void unsetDomain() {
      this.domain = null;
    }

    /** Returns true if field domain is set (has been assigned a value) and false otherwise */
    public boolean isSetDomain() {
      return this.domain != null;
    }

    public void setDomainIsSet(boolean value) {
      if (!value) {
        this.domain = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN:
        if (value == null) {
          unsetDomain();
        } else {
          setDomain((org.apache.airavata.sharing.registry.models.Domain)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN:
        return getDomain();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN:
        return isSetDomain();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updateDomain_args)
        return this.equals((updateDomain_args)that);
      return false;
    }

    public boolean equals(updateDomain_args that) {
      if (that == null)
        return false;

      boolean this_present_domain = true && this.isSetDomain();
      boolean that_present_domain = true && that.isSetDomain();
      if (this_present_domain || that_present_domain) {
        if (!(this_present_domain && that_present_domain))
          return false;
        if (!this.domain.equals(that.domain))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domain = true && (isSetDomain());
      list.add(present_domain);
      if (present_domain)
        list.add(domain);

      return list.hashCode();
    }

    @Override
    public int compareTo(updateDomain_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomain()).compareTo(other.isSetDomain());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomain()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domain, other.domain);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updateDomain_args(");
      boolean first = true;

      sb.append("domain:");
      if (this.domain == null) {
        sb.append("null");
      } else {
        sb.append(this.domain);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domain == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domain' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
      if (domain != null) {
        domain.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updateDomain_argsStandardSchemeFactory implements SchemeFactory {
      public updateDomain_argsStandardScheme getScheme() {
        return new updateDomain_argsStandardScheme();
      }
    }

    private static class updateDomain_argsStandardScheme extends StandardScheme<updateDomain_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updateDomain_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.domain = new org.apache.airavata.sharing.registry.models.Domain();
                struct.domain.read(iprot);
                struct.setDomainIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updateDomain_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domain != null) {
          oprot.writeFieldBegin(DOMAIN_FIELD_DESC);
          struct.domain.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updateDomain_argsTupleSchemeFactory implements SchemeFactory {
      public updateDomain_argsTupleScheme getScheme() {
        return new updateDomain_argsTupleScheme();
      }
    }

    private static class updateDomain_argsTupleScheme extends TupleScheme<updateDomain_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updateDomain_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        struct.domain.write(oprot);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updateDomain_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domain = new org.apache.airavata.sharing.registry.models.Domain();
        struct.domain.read(iprot);
        struct.setDomainIsSet(true);
      }
    }

  }

  public static class updateDomain_result implements org.apache.thrift.TBase<updateDomain_result, updateDomain_result._Fields>, java.io.Serializable, Cloneable, Comparable<updateDomain_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updateDomain_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updateDomain_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updateDomain_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updateDomain_result.class, metaDataMap);
    }

    public updateDomain_result() {
    }

    public updateDomain_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updateDomain_result(updateDomain_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public updateDomain_result deepCopy() {
      return new updateDomain_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public updateDomain_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public updateDomain_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updateDomain_result)
        return this.equals((updateDomain_result)that);
      return false;
    }

    public boolean equals(updateDomain_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(updateDomain_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updateDomain_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updateDomain_resultStandardSchemeFactory implements SchemeFactory {
      public updateDomain_resultStandardScheme getScheme() {
        return new updateDomain_resultStandardScheme();
      }
    }

    private static class updateDomain_resultStandardScheme extends StandardScheme<updateDomain_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updateDomain_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updateDomain_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updateDomain_resultTupleSchemeFactory implements SchemeFactory {
      public updateDomain_resultTupleScheme getScheme() {
        return new updateDomain_resultTupleScheme();
      }
    }

    private static class updateDomain_resultTupleScheme extends TupleScheme<updateDomain_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updateDomain_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updateDomain_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class isDomainExists_args implements org.apache.thrift.TBase<isDomainExists_args, isDomainExists_args._Fields>, java.io.Serializable, Cloneable, Comparable<isDomainExists_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("isDomainExists_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new isDomainExists_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new isDomainExists_argsTupleSchemeFactory());
    }

    public String domainId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(isDomainExists_args.class, metaDataMap);
    }

    public isDomainExists_args() {
    }

    public isDomainExists_args(
      String domainId)
    {
      this();
      this.domainId = domainId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public isDomainExists_args(isDomainExists_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
    }

    public isDomainExists_args deepCopy() {
      return new isDomainExists_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public isDomainExists_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof isDomainExists_args)
        return this.equals((isDomainExists_args)that);
      return false;
    }

    public boolean equals(isDomainExists_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      return list.hashCode();
    }

    @Override
    public int compareTo(isDomainExists_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("isDomainExists_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class isDomainExists_argsStandardSchemeFactory implements SchemeFactory {
      public isDomainExists_argsStandardScheme getScheme() {
        return new isDomainExists_argsStandardScheme();
      }
    }

    private static class isDomainExists_argsStandardScheme extends StandardScheme<isDomainExists_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, isDomainExists_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, isDomainExists_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class isDomainExists_argsTupleSchemeFactory implements SchemeFactory {
      public isDomainExists_argsTupleScheme getScheme() {
        return new isDomainExists_argsTupleScheme();
      }
    }

    private static class isDomainExists_argsTupleScheme extends TupleScheme<isDomainExists_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, isDomainExists_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, isDomainExists_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
      }
    }

  }

  public static class isDomainExists_result implements org.apache.thrift.TBase<isDomainExists_result, isDomainExists_result._Fields>, java.io.Serializable, Cloneable, Comparable<isDomainExists_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("isDomainExists_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new isDomainExists_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new isDomainExists_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(isDomainExists_result.class, metaDataMap);
    }

    public isDomainExists_result() {
    }

    public isDomainExists_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public isDomainExists_result(isDomainExists_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public isDomainExists_result deepCopy() {
      return new isDomainExists_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public isDomainExists_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public isDomainExists_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof isDomainExists_result)
        return this.equals((isDomainExists_result)that);
      return false;
    }

    public boolean equals(isDomainExists_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(isDomainExists_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("isDomainExists_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class isDomainExists_resultStandardSchemeFactory implements SchemeFactory {
      public isDomainExists_resultStandardScheme getScheme() {
        return new isDomainExists_resultStandardScheme();
      }
    }

    private static class isDomainExists_resultStandardScheme extends StandardScheme<isDomainExists_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, isDomainExists_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, isDomainExists_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class isDomainExists_resultTupleSchemeFactory implements SchemeFactory {
      public isDomainExists_resultTupleScheme getScheme() {
        return new isDomainExists_resultTupleScheme();
      }
    }

    private static class isDomainExists_resultTupleScheme extends TupleScheme<isDomainExists_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, isDomainExists_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, isDomainExists_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class deleteDomain_args implements org.apache.thrift.TBase<deleteDomain_args, deleteDomain_args._Fields>, java.io.Serializable, Cloneable, Comparable<deleteDomain_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deleteDomain_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deleteDomain_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deleteDomain_argsTupleSchemeFactory());
    }

    public String domainId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deleteDomain_args.class, metaDataMap);
    }

    public deleteDomain_args() {
    }

    public deleteDomain_args(
      String domainId)
    {
      this();
      this.domainId = domainId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deleteDomain_args(deleteDomain_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
    }

    public deleteDomain_args deepCopy() {
      return new deleteDomain_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public deleteDomain_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deleteDomain_args)
        return this.equals((deleteDomain_args)that);
      return false;
    }

    public boolean equals(deleteDomain_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      return list.hashCode();
    }

    @Override
    public int compareTo(deleteDomain_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deleteDomain_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deleteDomain_argsStandardSchemeFactory implements SchemeFactory {
      public deleteDomain_argsStandardScheme getScheme() {
        return new deleteDomain_argsStandardScheme();
      }
    }

    private static class deleteDomain_argsStandardScheme extends StandardScheme<deleteDomain_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deleteDomain_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deleteDomain_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deleteDomain_argsTupleSchemeFactory implements SchemeFactory {
      public deleteDomain_argsTupleScheme getScheme() {
        return new deleteDomain_argsTupleScheme();
      }
    }

    private static class deleteDomain_argsTupleScheme extends TupleScheme<deleteDomain_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deleteDomain_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deleteDomain_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
      }
    }

  }

  public static class deleteDomain_result implements org.apache.thrift.TBase<deleteDomain_result, deleteDomain_result._Fields>, java.io.Serializable, Cloneable, Comparable<deleteDomain_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deleteDomain_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deleteDomain_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deleteDomain_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deleteDomain_result.class, metaDataMap);
    }

    public deleteDomain_result() {
    }

    public deleteDomain_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deleteDomain_result(deleteDomain_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public deleteDomain_result deepCopy() {
      return new deleteDomain_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public deleteDomain_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public deleteDomain_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deleteDomain_result)
        return this.equals((deleteDomain_result)that);
      return false;
    }

    public boolean equals(deleteDomain_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(deleteDomain_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deleteDomain_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deleteDomain_resultStandardSchemeFactory implements SchemeFactory {
      public deleteDomain_resultStandardScheme getScheme() {
        return new deleteDomain_resultStandardScheme();
      }
    }

    private static class deleteDomain_resultStandardScheme extends StandardScheme<deleteDomain_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deleteDomain_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deleteDomain_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deleteDomain_resultTupleSchemeFactory implements SchemeFactory {
      public deleteDomain_resultTupleScheme getScheme() {
        return new deleteDomain_resultTupleScheme();
      }
    }

    private static class deleteDomain_resultTupleScheme extends TupleScheme<deleteDomain_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deleteDomain_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deleteDomain_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getDomain_args implements org.apache.thrift.TBase<getDomain_args, getDomain_args._Fields>, java.io.Serializable, Cloneable, Comparable<getDomain_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getDomain_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getDomain_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getDomain_argsTupleSchemeFactory());
    }

    public String domainId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getDomain_args.class, metaDataMap);
    }

    public getDomain_args() {
    }

    public getDomain_args(
      String domainId)
    {
      this();
      this.domainId = domainId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getDomain_args(getDomain_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
    }

    public getDomain_args deepCopy() {
      return new getDomain_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getDomain_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getDomain_args)
        return this.equals((getDomain_args)that);
      return false;
    }

    public boolean equals(getDomain_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      return list.hashCode();
    }

    @Override
    public int compareTo(getDomain_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getDomain_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getDomain_argsStandardSchemeFactory implements SchemeFactory {
      public getDomain_argsStandardScheme getScheme() {
        return new getDomain_argsStandardScheme();
      }
    }

    private static class getDomain_argsStandardScheme extends StandardScheme<getDomain_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getDomain_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getDomain_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getDomain_argsTupleSchemeFactory implements SchemeFactory {
      public getDomain_argsTupleScheme getScheme() {
        return new getDomain_argsTupleScheme();
      }
    }

    private static class getDomain_argsTupleScheme extends TupleScheme<getDomain_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getDomain_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getDomain_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
      }
    }

  }

  public static class getDomain_result implements org.apache.thrift.TBase<getDomain_result, getDomain_result._Fields>, java.io.Serializable, Cloneable, Comparable<getDomain_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getDomain_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getDomain_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getDomain_resultTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.Domain success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.Domain.class)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getDomain_result.class, metaDataMap);
    }

    public getDomain_result() {
    }

    public getDomain_result(
      org.apache.airavata.sharing.registry.models.Domain success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getDomain_result(getDomain_result other) {
      if (other.isSetSuccess()) {
        this.success = new org.apache.airavata.sharing.registry.models.Domain(other.success);
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getDomain_result deepCopy() {
      return new getDomain_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public org.apache.airavata.sharing.registry.models.Domain getSuccess() {
      return this.success;
    }

    public getDomain_result setSuccess(org.apache.airavata.sharing.registry.models.Domain success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getDomain_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((org.apache.airavata.sharing.registry.models.Domain)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getDomain_result)
        return this.equals((getDomain_result)that);
      return false;
    }

    public boolean equals(getDomain_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getDomain_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getDomain_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getDomain_resultStandardSchemeFactory implements SchemeFactory {
      public getDomain_resultStandardScheme getScheme() {
        return new getDomain_resultStandardScheme();
      }
    }

    private static class getDomain_resultStandardScheme extends StandardScheme<getDomain_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getDomain_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new org.apache.airavata.sharing.registry.models.Domain();
                struct.success.read(iprot);
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getDomain_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getDomain_resultTupleSchemeFactory implements SchemeFactory {
      public getDomain_resultTupleScheme getScheme() {
        return new getDomain_resultTupleScheme();
      }
    }

    private static class getDomain_resultTupleScheme extends TupleScheme<getDomain_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getDomain_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          struct.success.write(oprot);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getDomain_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = new org.apache.airavata.sharing.registry.models.Domain();
          struct.success.read(iprot);
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getDomains_args implements org.apache.thrift.TBase<getDomains_args, getDomains_args._Fields>, java.io.Serializable, Cloneable, Comparable<getDomains_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getDomains_args");

    private static final org.apache.thrift.protocol.TField OFFSET_FIELD_DESC = new org.apache.thrift.protocol.TField("offset", org.apache.thrift.protocol.TType.I32, (short)1);
    private static final org.apache.thrift.protocol.TField LIMIT_FIELD_DESC = new org.apache.thrift.protocol.TField("limit", org.apache.thrift.protocol.TType.I32, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getDomains_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getDomains_argsTupleSchemeFactory());
    }

    public int offset; // required
    public int limit; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      OFFSET((short)1, "offset"),
      LIMIT((short)2, "limit");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // OFFSET
            return OFFSET;
          case 2: // LIMIT
            return LIMIT;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __OFFSET_ISSET_ID = 0;
    private static final int __LIMIT_ISSET_ID = 1;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.OFFSET, new org.apache.thrift.meta_data.FieldMetaData("offset", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      tmpMap.put(_Fields.LIMIT, new org.apache.thrift.meta_data.FieldMetaData("limit", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getDomains_args.class, metaDataMap);
    }

    public getDomains_args() {
    }

    public getDomains_args(
      int offset,
      int limit)
    {
      this();
      this.offset = offset;
      setOffsetIsSet(true);
      this.limit = limit;
      setLimitIsSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getDomains_args(getDomains_args other) {
      __isset_bitfield = other.__isset_bitfield;
      this.offset = other.offset;
      this.limit = other.limit;
    }

    public getDomains_args deepCopy() {
      return new getDomains_args(this);
    }

    @Override
    public void clear() {
      setOffsetIsSet(false);
      this.offset = 0;
      setLimitIsSet(false);
      this.limit = 0;
    }

    public int getOffset() {
      return this.offset;
    }

    public getDomains_args setOffset(int offset) {
      this.offset = offset;
      setOffsetIsSet(true);
      return this;
    }

    public void unsetOffset() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    /** Returns true if field offset is set (has been assigned a value) and false otherwise */
    public boolean isSetOffset() {
      return EncodingUtils.testBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    public void setOffsetIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __OFFSET_ISSET_ID, value);
    }

    public int getLimit() {
      return this.limit;
    }

    public getDomains_args setLimit(int limit) {
      this.limit = limit;
      setLimitIsSet(true);
      return this;
    }

    public void unsetLimit() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    /** Returns true if field limit is set (has been assigned a value) and false otherwise */
    public boolean isSetLimit() {
      return EncodingUtils.testBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    public void setLimitIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __LIMIT_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case OFFSET:
        if (value == null) {
          unsetOffset();
        } else {
          setOffset((Integer)value);
        }
        break;

      case LIMIT:
        if (value == null) {
          unsetLimit();
        } else {
          setLimit((Integer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case OFFSET:
        return getOffset();

      case LIMIT:
        return getLimit();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case OFFSET:
        return isSetOffset();
      case LIMIT:
        return isSetLimit();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getDomains_args)
        return this.equals((getDomains_args)that);
      return false;
    }

    public boolean equals(getDomains_args that) {
      if (that == null)
        return false;

      boolean this_present_offset = true;
      boolean that_present_offset = true;
      if (this_present_offset || that_present_offset) {
        if (!(this_present_offset && that_present_offset))
          return false;
        if (this.offset != that.offset)
          return false;
      }

      boolean this_present_limit = true;
      boolean that_present_limit = true;
      if (this_present_limit || that_present_limit) {
        if (!(this_present_limit && that_present_limit))
          return false;
        if (this.limit != that.limit)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_offset = true;
      list.add(present_offset);
      if (present_offset)
        list.add(offset);

      boolean present_limit = true;
      list.add(present_limit);
      if (present_limit)
        list.add(limit);

      return list.hashCode();
    }

    @Override
    public int compareTo(getDomains_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetOffset()).compareTo(other.isSetOffset());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetOffset()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.offset, other.offset);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetLimit()).compareTo(other.isSetLimit());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetLimit()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.limit, other.limit);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getDomains_args(");
      boolean first = true;

      sb.append("offset:");
      sb.append(this.offset);
      first = false;
      if (!first) sb.append(", ");
      sb.append("limit:");
      sb.append(this.limit);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // alas, we cannot check 'offset' because it's a primitive and you chose the non-beans generator.
      // alas, we cannot check 'limit' because it's a primitive and you chose the non-beans generator.
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getDomains_argsStandardSchemeFactory implements SchemeFactory {
      public getDomains_argsStandardScheme getScheme() {
        return new getDomains_argsStandardScheme();
      }
    }

    private static class getDomains_argsStandardScheme extends StandardScheme<getDomains_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getDomains_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // OFFSET
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.offset = iprot.readI32();
                struct.setOffsetIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // LIMIT
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.limit = iprot.readI32();
                struct.setLimitIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        if (!struct.isSetOffset()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'offset' was not found in serialized data! Struct: " + toString());
        }
        if (!struct.isSetLimit()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'limit' was not found in serialized data! Struct: " + toString());
        }
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getDomains_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        oprot.writeFieldBegin(OFFSET_FIELD_DESC);
        oprot.writeI32(struct.offset);
        oprot.writeFieldEnd();
        oprot.writeFieldBegin(LIMIT_FIELD_DESC);
        oprot.writeI32(struct.limit);
        oprot.writeFieldEnd();
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getDomains_argsTupleSchemeFactory implements SchemeFactory {
      public getDomains_argsTupleScheme getScheme() {
        return new getDomains_argsTupleScheme();
      }
    }

    private static class getDomains_argsTupleScheme extends TupleScheme<getDomains_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getDomains_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeI32(struct.offset);
        oprot.writeI32(struct.limit);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getDomains_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.offset = iprot.readI32();
        struct.setOffsetIsSet(true);
        struct.limit = iprot.readI32();
        struct.setLimitIsSet(true);
      }
    }

  }

  public static class getDomains_result implements org.apache.thrift.TBase<getDomains_result, getDomains_result._Fields>, java.io.Serializable, Cloneable, Comparable<getDomains_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getDomains_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getDomains_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getDomains_resultTupleSchemeFactory());
    }

    public List<org.apache.airavata.sharing.registry.models.Domain> success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.Domain.class))));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getDomains_result.class, metaDataMap);
    }

    public getDomains_result() {
    }

    public getDomains_result(
      List<org.apache.airavata.sharing.registry.models.Domain> success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getDomains_result(getDomains_result other) {
      if (other.isSetSuccess()) {
        List<org.apache.airavata.sharing.registry.models.Domain> __this__success = new ArrayList<org.apache.airavata.sharing.registry.models.Domain>(other.success.size());
        for (org.apache.airavata.sharing.registry.models.Domain other_element : other.success) {
          __this__success.add(new org.apache.airavata.sharing.registry.models.Domain(other_element));
        }
        this.success = __this__success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getDomains_result deepCopy() {
      return new getDomains_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public int getSuccessSize() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<org.apache.airavata.sharing.registry.models.Domain> getSuccessIterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void addToSuccess(org.apache.airavata.sharing.registry.models.Domain elem) {
      if (this.success == null) {
        this.success = new ArrayList<org.apache.airavata.sharing.registry.models.Domain>();
      }
      this.success.add(elem);
    }

    public List<org.apache.airavata.sharing.registry.models.Domain> getSuccess() {
      return this.success;
    }

    public getDomains_result setSuccess(List<org.apache.airavata.sharing.registry.models.Domain> success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getDomains_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((List<org.apache.airavata.sharing.registry.models.Domain>)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getDomains_result)
        return this.equals((getDomains_result)that);
      return false;
    }

    public boolean equals(getDomains_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getDomains_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getDomains_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getDomains_resultStandardSchemeFactory implements SchemeFactory {
      public getDomains_resultStandardScheme getScheme() {
        return new getDomains_resultStandardScheme();
      }
    }

    private static class getDomains_resultStandardScheme extends StandardScheme<getDomains_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getDomains_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list0 = iprot.readListBegin();
                  struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.Domain>(_list0.size);
                  org.apache.airavata.sharing.registry.models.Domain _elem1;
                  for (int _i2 = 0; _i2 < _list0.size; ++_i2)
                  {
                    _elem1 = new org.apache.airavata.sharing.registry.models.Domain();
                    _elem1.read(iprot);
                    struct.success.add(_elem1);
                  }
                  iprot.readListEnd();
                }
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getDomains_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (org.apache.airavata.sharing.registry.models.Domain _iter3 : struct.success)
            {
              _iter3.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getDomains_resultTupleSchemeFactory implements SchemeFactory {
      public getDomains_resultTupleScheme getScheme() {
        return new getDomains_resultTupleScheme();
      }
    }

    private static class getDomains_resultTupleScheme extends TupleScheme<getDomains_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getDomains_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          {
            oprot.writeI32(struct.success.size());
            for (org.apache.airavata.sharing.registry.models.Domain _iter4 : struct.success)
            {
              _iter4.write(oprot);
            }
          }
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getDomains_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list5 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.Domain>(_list5.size);
            org.apache.airavata.sharing.registry.models.Domain _elem6;
            for (int _i7 = 0; _i7 < _list5.size; ++_i7)
            {
              _elem6 = new org.apache.airavata.sharing.registry.models.Domain();
              _elem6.read(iprot);
              struct.success.add(_elem6);
            }
          }
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class createUser_args implements org.apache.thrift.TBase<createUser_args, createUser_args._Fields>, java.io.Serializable, Cloneable, Comparable<createUser_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createUser_args");

    private static final org.apache.thrift.protocol.TField USER_FIELD_DESC = new org.apache.thrift.protocol.TField("user", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new createUser_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new createUser_argsTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.User user; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      USER((short)1, "user");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // USER
            return USER;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.USER, new org.apache.thrift.meta_data.FieldMetaData("user", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.User.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createUser_args.class, metaDataMap);
    }

    public createUser_args() {
    }

    public createUser_args(
      org.apache.airavata.sharing.registry.models.User user)
    {
      this();
      this.user = user;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public createUser_args(createUser_args other) {
      if (other.isSetUser()) {
        this.user = new org.apache.airavata.sharing.registry.models.User(other.user);
      }
    }

    public createUser_args deepCopy() {
      return new createUser_args(this);
    }

    @Override
    public void clear() {
      this.user = null;
    }

    public org.apache.airavata.sharing.registry.models.User getUser() {
      return this.user;
    }

    public createUser_args setUser(org.apache.airavata.sharing.registry.models.User user) {
      this.user = user;
      return this;
    }

    public void unsetUser() {
      this.user = null;
    }

    /** Returns true if field user is set (has been assigned a value) and false otherwise */
    public boolean isSetUser() {
      return this.user != null;
    }

    public void setUserIsSet(boolean value) {
      if (!value) {
        this.user = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case USER:
        if (value == null) {
          unsetUser();
        } else {
          setUser((org.apache.airavata.sharing.registry.models.User)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case USER:
        return getUser();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case USER:
        return isSetUser();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof createUser_args)
        return this.equals((createUser_args)that);
      return false;
    }

    public boolean equals(createUser_args that) {
      if (that == null)
        return false;

      boolean this_present_user = true && this.isSetUser();
      boolean that_present_user = true && that.isSetUser();
      if (this_present_user || that_present_user) {
        if (!(this_present_user && that_present_user))
          return false;
        if (!this.user.equals(that.user))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_user = true && (isSetUser());
      list.add(present_user);
      if (present_user)
        list.add(user);

      return list.hashCode();
    }

    @Override
    public int compareTo(createUser_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetUser()).compareTo(other.isSetUser());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetUser()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.user, other.user);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("createUser_args(");
      boolean first = true;

      sb.append("user:");
      if (this.user == null) {
        sb.append("null");
      } else {
        sb.append(this.user);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (user == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'user' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
      if (user != null) {
        user.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class createUser_argsStandardSchemeFactory implements SchemeFactory {
      public createUser_argsStandardScheme getScheme() {
        return new createUser_argsStandardScheme();
      }
    }

    private static class createUser_argsStandardScheme extends StandardScheme<createUser_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, createUser_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // USER
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.user = new org.apache.airavata.sharing.registry.models.User();
                struct.user.read(iprot);
                struct.setUserIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, createUser_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.user != null) {
          oprot.writeFieldBegin(USER_FIELD_DESC);
          struct.user.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class createUser_argsTupleSchemeFactory implements SchemeFactory {
      public createUser_argsTupleScheme getScheme() {
        return new createUser_argsTupleScheme();
      }
    }

    private static class createUser_argsTupleScheme extends TupleScheme<createUser_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, createUser_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        struct.user.write(oprot);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, createUser_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.user = new org.apache.airavata.sharing.registry.models.User();
        struct.user.read(iprot);
        struct.setUserIsSet(true);
      }
    }

  }

  public static class createUser_result implements org.apache.thrift.TBase<createUser_result, createUser_result._Fields>, java.io.Serializable, Cloneable, Comparable<createUser_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createUser_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);
    private static final org.apache.thrift.protocol.TField DEE_FIELD_DESC = new org.apache.thrift.protocol.TField("dee", org.apache.thrift.protocol.TType.STRUCT, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new createUser_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new createUser_resultTupleSchemeFactory());
    }

    public String success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required
    public org.apache.airavata.sharing.registry.models.DuplicateEntryException dee; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre"),
      DEE((short)2, "dee");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          case 2: // DEE
            return DEE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      tmpMap.put(_Fields.DEE, new org.apache.thrift.meta_data.FieldMetaData("dee", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createUser_result.class, metaDataMap);
    }

    public createUser_result() {
    }

    public createUser_result(
      String success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre,
      org.apache.airavata.sharing.registry.models.DuplicateEntryException dee)
    {
      this();
      this.success = success;
      this.sre = sre;
      this.dee = dee;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public createUser_result(createUser_result other) {
      if (other.isSetSuccess()) {
        this.success = other.success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
      if (other.isSetDee()) {
        this.dee = new org.apache.airavata.sharing.registry.models.DuplicateEntryException(other.dee);
      }
    }

    public createUser_result deepCopy() {
      return new createUser_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
      this.dee = null;
    }

    public String getSuccess() {
      return this.success;
    }

    public createUser_result setSuccess(String success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public createUser_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.DuplicateEntryException getDee() {
      return this.dee;
    }

    public createUser_result setDee(org.apache.airavata.sharing.registry.models.DuplicateEntryException dee) {
      this.dee = dee;
      return this;
    }

    public void unsetDee() {
      this.dee = null;
    }

    /** Returns true if field dee is set (has been assigned a value) and false otherwise */
    public boolean isSetDee() {
      return this.dee != null;
    }

    public void setDeeIsSet(boolean value) {
      if (!value) {
        this.dee = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((String)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      case DEE:
        if (value == null) {
          unsetDee();
        } else {
          setDee((org.apache.airavata.sharing.registry.models.DuplicateEntryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      case DEE:
        return getDee();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      case DEE:
        return isSetDee();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof createUser_result)
        return this.equals((createUser_result)that);
      return false;
    }

    public boolean equals(createUser_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      boolean this_present_dee = true && this.isSetDee();
      boolean that_present_dee = true && that.isSetDee();
      if (this_present_dee || that_present_dee) {
        if (!(this_present_dee && that_present_dee))
          return false;
        if (!this.dee.equals(that.dee))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      boolean present_dee = true && (isSetDee());
      list.add(present_dee);
      if (present_dee)
        list.add(dee);

      return list.hashCode();
    }

    @Override
    public int compareTo(createUser_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetDee()).compareTo(other.isSetDee());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDee()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.dee, other.dee);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("createUser_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("dee:");
      if (this.dee == null) {
        sb.append("null");
      } else {
        sb.append(this.dee);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class createUser_resultStandardSchemeFactory implements SchemeFactory {
      public createUser_resultStandardScheme getScheme() {
        return new createUser_resultStandardScheme();
      }
    }

    private static class createUser_resultStandardScheme extends StandardScheme<createUser_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, createUser_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.success = iprot.readString();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // DEE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.dee = new org.apache.airavata.sharing.registry.models.DuplicateEntryException();
                struct.dee.read(iprot);
                struct.setDeeIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, createUser_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeString(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.dee != null) {
          oprot.writeFieldBegin(DEE_FIELD_DESC);
          struct.dee.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class createUser_resultTupleSchemeFactory implements SchemeFactory {
      public createUser_resultTupleScheme getScheme() {
        return new createUser_resultTupleScheme();
      }
    }

    private static class createUser_resultTupleScheme extends TupleScheme<createUser_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, createUser_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        if (struct.isSetDee()) {
          optionals.set(2);
        }
        oprot.writeBitSet(optionals, 3);
        if (struct.isSetSuccess()) {
          oprot.writeString(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
        if (struct.isSetDee()) {
          struct.dee.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, createUser_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(3);
        if (incoming.get(0)) {
          struct.success = iprot.readString();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
        if (incoming.get(2)) {
          struct.dee = new org.apache.airavata.sharing.registry.models.DuplicateEntryException();
          struct.dee.read(iprot);
          struct.setDeeIsSet(true);
        }
      }
    }

  }

  public static class updatedUser_args implements org.apache.thrift.TBase<updatedUser_args, updatedUser_args._Fields>, java.io.Serializable, Cloneable, Comparable<updatedUser_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updatedUser_args");

    private static final org.apache.thrift.protocol.TField USER_FIELD_DESC = new org.apache.thrift.protocol.TField("user", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updatedUser_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updatedUser_argsTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.User user; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      USER((short)1, "user");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // USER
            return USER;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.USER, new org.apache.thrift.meta_data.FieldMetaData("user", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.User.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updatedUser_args.class, metaDataMap);
    }

    public updatedUser_args() {
    }

    public updatedUser_args(
      org.apache.airavata.sharing.registry.models.User user)
    {
      this();
      this.user = user;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updatedUser_args(updatedUser_args other) {
      if (other.isSetUser()) {
        this.user = new org.apache.airavata.sharing.registry.models.User(other.user);
      }
    }

    public updatedUser_args deepCopy() {
      return new updatedUser_args(this);
    }

    @Override
    public void clear() {
      this.user = null;
    }

    public org.apache.airavata.sharing.registry.models.User getUser() {
      return this.user;
    }

    public updatedUser_args setUser(org.apache.airavata.sharing.registry.models.User user) {
      this.user = user;
      return this;
    }

    public void unsetUser() {
      this.user = null;
    }

    /** Returns true if field user is set (has been assigned a value) and false otherwise */
    public boolean isSetUser() {
      return this.user != null;
    }

    public void setUserIsSet(boolean value) {
      if (!value) {
        this.user = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case USER:
        if (value == null) {
          unsetUser();
        } else {
          setUser((org.apache.airavata.sharing.registry.models.User)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case USER:
        return getUser();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case USER:
        return isSetUser();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updatedUser_args)
        return this.equals((updatedUser_args)that);
      return false;
    }

    public boolean equals(updatedUser_args that) {
      if (that == null)
        return false;

      boolean this_present_user = true && this.isSetUser();
      boolean that_present_user = true && that.isSetUser();
      if (this_present_user || that_present_user) {
        if (!(this_present_user && that_present_user))
          return false;
        if (!this.user.equals(that.user))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_user = true && (isSetUser());
      list.add(present_user);
      if (present_user)
        list.add(user);

      return list.hashCode();
    }

    @Override
    public int compareTo(updatedUser_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetUser()).compareTo(other.isSetUser());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetUser()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.user, other.user);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updatedUser_args(");
      boolean first = true;

      sb.append("user:");
      if (this.user == null) {
        sb.append("null");
      } else {
        sb.append(this.user);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (user == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'user' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
      if (user != null) {
        user.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updatedUser_argsStandardSchemeFactory implements SchemeFactory {
      public updatedUser_argsStandardScheme getScheme() {
        return new updatedUser_argsStandardScheme();
      }
    }

    private static class updatedUser_argsStandardScheme extends StandardScheme<updatedUser_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updatedUser_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // USER
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.user = new org.apache.airavata.sharing.registry.models.User();
                struct.user.read(iprot);
                struct.setUserIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updatedUser_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.user != null) {
          oprot.writeFieldBegin(USER_FIELD_DESC);
          struct.user.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updatedUser_argsTupleSchemeFactory implements SchemeFactory {
      public updatedUser_argsTupleScheme getScheme() {
        return new updatedUser_argsTupleScheme();
      }
    }

    private static class updatedUser_argsTupleScheme extends TupleScheme<updatedUser_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updatedUser_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        struct.user.write(oprot);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updatedUser_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.user = new org.apache.airavata.sharing.registry.models.User();
        struct.user.read(iprot);
        struct.setUserIsSet(true);
      }
    }

  }

  public static class updatedUser_result implements org.apache.thrift.TBase<updatedUser_result, updatedUser_result._Fields>, java.io.Serializable, Cloneable, Comparable<updatedUser_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updatedUser_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updatedUser_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updatedUser_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updatedUser_result.class, metaDataMap);
    }

    public updatedUser_result() {
    }

    public updatedUser_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updatedUser_result(updatedUser_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public updatedUser_result deepCopy() {
      return new updatedUser_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public updatedUser_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public updatedUser_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updatedUser_result)
        return this.equals((updatedUser_result)that);
      return false;
    }

    public boolean equals(updatedUser_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(updatedUser_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updatedUser_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updatedUser_resultStandardSchemeFactory implements SchemeFactory {
      public updatedUser_resultStandardScheme getScheme() {
        return new updatedUser_resultStandardScheme();
      }
    }

    private static class updatedUser_resultStandardScheme extends StandardScheme<updatedUser_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updatedUser_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updatedUser_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updatedUser_resultTupleSchemeFactory implements SchemeFactory {
      public updatedUser_resultTupleScheme getScheme() {
        return new updatedUser_resultTupleScheme();
      }
    }

    private static class updatedUser_resultTupleScheme extends TupleScheme<updatedUser_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updatedUser_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updatedUser_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class isUserExists_args implements org.apache.thrift.TBase<isUserExists_args, isUserExists_args._Fields>, java.io.Serializable, Cloneable, Comparable<isUserExists_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("isUserExists_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField USER_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("userId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new isUserExists_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new isUserExists_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String userId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      USER_ID((short)2, "userId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // USER_ID
            return USER_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.USER_ID, new org.apache.thrift.meta_data.FieldMetaData("userId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(isUserExists_args.class, metaDataMap);
    }

    public isUserExists_args() {
    }

    public isUserExists_args(
      String domainId,
      String userId)
    {
      this();
      this.domainId = domainId;
      this.userId = userId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public isUserExists_args(isUserExists_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetUserId()) {
        this.userId = other.userId;
      }
    }

    public isUserExists_args deepCopy() {
      return new isUserExists_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.userId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public isUserExists_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getUserId() {
      return this.userId;
    }

    public isUserExists_args setUserId(String userId) {
      this.userId = userId;
      return this;
    }

    public void unsetUserId() {
      this.userId = null;
    }

    /** Returns true if field userId is set (has been assigned a value) and false otherwise */
    public boolean isSetUserId() {
      return this.userId != null;
    }

    public void setUserIdIsSet(boolean value) {
      if (!value) {
        this.userId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case USER_ID:
        if (value == null) {
          unsetUserId();
        } else {
          setUserId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case USER_ID:
        return getUserId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case USER_ID:
        return isSetUserId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof isUserExists_args)
        return this.equals((isUserExists_args)that);
      return false;
    }

    public boolean equals(isUserExists_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_userId = true && this.isSetUserId();
      boolean that_present_userId = true && that.isSetUserId();
      if (this_present_userId || that_present_userId) {
        if (!(this_present_userId && that_present_userId))
          return false;
        if (!this.userId.equals(that.userId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_userId = true && (isSetUserId());
      list.add(present_userId);
      if (present_userId)
        list.add(userId);

      return list.hashCode();
    }

    @Override
    public int compareTo(isUserExists_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetUserId()).compareTo(other.isSetUserId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetUserId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.userId, other.userId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("isUserExists_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("userId:");
      if (this.userId == null) {
        sb.append("null");
      } else {
        sb.append(this.userId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (userId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'userId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class isUserExists_argsStandardSchemeFactory implements SchemeFactory {
      public isUserExists_argsStandardScheme getScheme() {
        return new isUserExists_argsStandardScheme();
      }
    }

    private static class isUserExists_argsStandardScheme extends StandardScheme<isUserExists_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, isUserExists_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // USER_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.userId = iprot.readString();
                struct.setUserIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, isUserExists_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.userId != null) {
          oprot.writeFieldBegin(USER_ID_FIELD_DESC);
          oprot.writeString(struct.userId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class isUserExists_argsTupleSchemeFactory implements SchemeFactory {
      public isUserExists_argsTupleScheme getScheme() {
        return new isUserExists_argsTupleScheme();
      }
    }

    private static class isUserExists_argsTupleScheme extends TupleScheme<isUserExists_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, isUserExists_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.userId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, isUserExists_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.userId = iprot.readString();
        struct.setUserIdIsSet(true);
      }
    }

  }

  public static class isUserExists_result implements org.apache.thrift.TBase<isUserExists_result, isUserExists_result._Fields>, java.io.Serializable, Cloneable, Comparable<isUserExists_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("isUserExists_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new isUserExists_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new isUserExists_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(isUserExists_result.class, metaDataMap);
    }

    public isUserExists_result() {
    }

    public isUserExists_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public isUserExists_result(isUserExists_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public isUserExists_result deepCopy() {
      return new isUserExists_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public isUserExists_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public isUserExists_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof isUserExists_result)
        return this.equals((isUserExists_result)that);
      return false;
    }

    public boolean equals(isUserExists_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(isUserExists_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("isUserExists_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class isUserExists_resultStandardSchemeFactory implements SchemeFactory {
      public isUserExists_resultStandardScheme getScheme() {
        return new isUserExists_resultStandardScheme();
      }
    }

    private static class isUserExists_resultStandardScheme extends StandardScheme<isUserExists_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, isUserExists_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, isUserExists_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class isUserExists_resultTupleSchemeFactory implements SchemeFactory {
      public isUserExists_resultTupleScheme getScheme() {
        return new isUserExists_resultTupleScheme();
      }
    }

    private static class isUserExists_resultTupleScheme extends TupleScheme<isUserExists_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, isUserExists_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, isUserExists_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class deleteUser_args implements org.apache.thrift.TBase<deleteUser_args, deleteUser_args._Fields>, java.io.Serializable, Cloneable, Comparable<deleteUser_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deleteUser_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField USER_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("userId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deleteUser_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deleteUser_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String userId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      USER_ID((short)2, "userId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // USER_ID
            return USER_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.USER_ID, new org.apache.thrift.meta_data.FieldMetaData("userId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deleteUser_args.class, metaDataMap);
    }

    public deleteUser_args() {
    }

    public deleteUser_args(
      String domainId,
      String userId)
    {
      this();
      this.domainId = domainId;
      this.userId = userId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deleteUser_args(deleteUser_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetUserId()) {
        this.userId = other.userId;
      }
    }

    public deleteUser_args deepCopy() {
      return new deleteUser_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.userId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public deleteUser_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getUserId() {
      return this.userId;
    }

    public deleteUser_args setUserId(String userId) {
      this.userId = userId;
      return this;
    }

    public void unsetUserId() {
      this.userId = null;
    }

    /** Returns true if field userId is set (has been assigned a value) and false otherwise */
    public boolean isSetUserId() {
      return this.userId != null;
    }

    public void setUserIdIsSet(boolean value) {
      if (!value) {
        this.userId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case USER_ID:
        if (value == null) {
          unsetUserId();
        } else {
          setUserId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case USER_ID:
        return getUserId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case USER_ID:
        return isSetUserId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deleteUser_args)
        return this.equals((deleteUser_args)that);
      return false;
    }

    public boolean equals(deleteUser_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_userId = true && this.isSetUserId();
      boolean that_present_userId = true && that.isSetUserId();
      if (this_present_userId || that_present_userId) {
        if (!(this_present_userId && that_present_userId))
          return false;
        if (!this.userId.equals(that.userId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_userId = true && (isSetUserId());
      list.add(present_userId);
      if (present_userId)
        list.add(userId);

      return list.hashCode();
    }

    @Override
    public int compareTo(deleteUser_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetUserId()).compareTo(other.isSetUserId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetUserId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.userId, other.userId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deleteUser_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("userId:");
      if (this.userId == null) {
        sb.append("null");
      } else {
        sb.append(this.userId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (userId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'userId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deleteUser_argsStandardSchemeFactory implements SchemeFactory {
      public deleteUser_argsStandardScheme getScheme() {
        return new deleteUser_argsStandardScheme();
      }
    }

    private static class deleteUser_argsStandardScheme extends StandardScheme<deleteUser_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deleteUser_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // USER_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.userId = iprot.readString();
                struct.setUserIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deleteUser_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.userId != null) {
          oprot.writeFieldBegin(USER_ID_FIELD_DESC);
          oprot.writeString(struct.userId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deleteUser_argsTupleSchemeFactory implements SchemeFactory {
      public deleteUser_argsTupleScheme getScheme() {
        return new deleteUser_argsTupleScheme();
      }
    }

    private static class deleteUser_argsTupleScheme extends TupleScheme<deleteUser_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deleteUser_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.userId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deleteUser_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.userId = iprot.readString();
        struct.setUserIdIsSet(true);
      }
    }

  }

  public static class deleteUser_result implements org.apache.thrift.TBase<deleteUser_result, deleteUser_result._Fields>, java.io.Serializable, Cloneable, Comparable<deleteUser_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deleteUser_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deleteUser_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deleteUser_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deleteUser_result.class, metaDataMap);
    }

    public deleteUser_result() {
    }

    public deleteUser_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deleteUser_result(deleteUser_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public deleteUser_result deepCopy() {
      return new deleteUser_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public deleteUser_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public deleteUser_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deleteUser_result)
        return this.equals((deleteUser_result)that);
      return false;
    }

    public boolean equals(deleteUser_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(deleteUser_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deleteUser_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deleteUser_resultStandardSchemeFactory implements SchemeFactory {
      public deleteUser_resultStandardScheme getScheme() {
        return new deleteUser_resultStandardScheme();
      }
    }

    private static class deleteUser_resultStandardScheme extends StandardScheme<deleteUser_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deleteUser_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deleteUser_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deleteUser_resultTupleSchemeFactory implements SchemeFactory {
      public deleteUser_resultTupleScheme getScheme() {
        return new deleteUser_resultTupleScheme();
      }
    }

    private static class deleteUser_resultTupleScheme extends TupleScheme<deleteUser_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deleteUser_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deleteUser_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getUser_args implements org.apache.thrift.TBase<getUser_args, getUser_args._Fields>, java.io.Serializable, Cloneable, Comparable<getUser_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getUser_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField USER_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("userId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getUser_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getUser_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String userId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      USER_ID((short)2, "userId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // USER_ID
            return USER_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.USER_ID, new org.apache.thrift.meta_data.FieldMetaData("userId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getUser_args.class, metaDataMap);
    }

    public getUser_args() {
    }

    public getUser_args(
      String domainId,
      String userId)
    {
      this();
      this.domainId = domainId;
      this.userId = userId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getUser_args(getUser_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetUserId()) {
        this.userId = other.userId;
      }
    }

    public getUser_args deepCopy() {
      return new getUser_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.userId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getUser_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getUserId() {
      return this.userId;
    }

    public getUser_args setUserId(String userId) {
      this.userId = userId;
      return this;
    }

    public void unsetUserId() {
      this.userId = null;
    }

    /** Returns true if field userId is set (has been assigned a value) and false otherwise */
    public boolean isSetUserId() {
      return this.userId != null;
    }

    public void setUserIdIsSet(boolean value) {
      if (!value) {
        this.userId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case USER_ID:
        if (value == null) {
          unsetUserId();
        } else {
          setUserId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case USER_ID:
        return getUserId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case USER_ID:
        return isSetUserId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getUser_args)
        return this.equals((getUser_args)that);
      return false;
    }

    public boolean equals(getUser_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_userId = true && this.isSetUserId();
      boolean that_present_userId = true && that.isSetUserId();
      if (this_present_userId || that_present_userId) {
        if (!(this_present_userId && that_present_userId))
          return false;
        if (!this.userId.equals(that.userId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_userId = true && (isSetUserId());
      list.add(present_userId);
      if (present_userId)
        list.add(userId);

      return list.hashCode();
    }

    @Override
    public int compareTo(getUser_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetUserId()).compareTo(other.isSetUserId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetUserId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.userId, other.userId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getUser_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("userId:");
      if (this.userId == null) {
        sb.append("null");
      } else {
        sb.append(this.userId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (userId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'userId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getUser_argsStandardSchemeFactory implements SchemeFactory {
      public getUser_argsStandardScheme getScheme() {
        return new getUser_argsStandardScheme();
      }
    }

    private static class getUser_argsStandardScheme extends StandardScheme<getUser_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getUser_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // USER_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.userId = iprot.readString();
                struct.setUserIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getUser_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.userId != null) {
          oprot.writeFieldBegin(USER_ID_FIELD_DESC);
          oprot.writeString(struct.userId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getUser_argsTupleSchemeFactory implements SchemeFactory {
      public getUser_argsTupleScheme getScheme() {
        return new getUser_argsTupleScheme();
      }
    }

    private static class getUser_argsTupleScheme extends TupleScheme<getUser_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getUser_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.userId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getUser_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.userId = iprot.readString();
        struct.setUserIdIsSet(true);
      }
    }

  }

  public static class getUser_result implements org.apache.thrift.TBase<getUser_result, getUser_result._Fields>, java.io.Serializable, Cloneable, Comparable<getUser_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getUser_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getUser_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getUser_resultTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.User success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.User.class)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getUser_result.class, metaDataMap);
    }

    public getUser_result() {
    }

    public getUser_result(
      org.apache.airavata.sharing.registry.models.User success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getUser_result(getUser_result other) {
      if (other.isSetSuccess()) {
        this.success = new org.apache.airavata.sharing.registry.models.User(other.success);
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getUser_result deepCopy() {
      return new getUser_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public org.apache.airavata.sharing.registry.models.User getSuccess() {
      return this.success;
    }

    public getUser_result setSuccess(org.apache.airavata.sharing.registry.models.User success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getUser_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((org.apache.airavata.sharing.registry.models.User)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getUser_result)
        return this.equals((getUser_result)that);
      return false;
    }

    public boolean equals(getUser_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getUser_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getUser_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getUser_resultStandardSchemeFactory implements SchemeFactory {
      public getUser_resultStandardScheme getScheme() {
        return new getUser_resultStandardScheme();
      }
    }

    private static class getUser_resultStandardScheme extends StandardScheme<getUser_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getUser_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new org.apache.airavata.sharing.registry.models.User();
                struct.success.read(iprot);
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getUser_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getUser_resultTupleSchemeFactory implements SchemeFactory {
      public getUser_resultTupleScheme getScheme() {
        return new getUser_resultTupleScheme();
      }
    }

    private static class getUser_resultTupleScheme extends TupleScheme<getUser_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getUser_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          struct.success.write(oprot);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getUser_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = new org.apache.airavata.sharing.registry.models.User();
          struct.success.read(iprot);
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getUsers_args implements org.apache.thrift.TBase<getUsers_args, getUsers_args._Fields>, java.io.Serializable, Cloneable, Comparable<getUsers_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getUsers_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField OFFSET_FIELD_DESC = new org.apache.thrift.protocol.TField("offset", org.apache.thrift.protocol.TType.I32, (short)2);
    private static final org.apache.thrift.protocol.TField LIMIT_FIELD_DESC = new org.apache.thrift.protocol.TField("limit", org.apache.thrift.protocol.TType.I32, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getUsers_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getUsers_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public int offset; // required
    public int limit; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      OFFSET((short)2, "offset"),
      LIMIT((short)3, "limit");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // OFFSET
            return OFFSET;
          case 3: // LIMIT
            return LIMIT;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __OFFSET_ISSET_ID = 0;
    private static final int __LIMIT_ISSET_ID = 1;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.OFFSET, new org.apache.thrift.meta_data.FieldMetaData("offset", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      tmpMap.put(_Fields.LIMIT, new org.apache.thrift.meta_data.FieldMetaData("limit", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getUsers_args.class, metaDataMap);
    }

    public getUsers_args() {
    }

    public getUsers_args(
      String domainId,
      int offset,
      int limit)
    {
      this();
      this.domainId = domainId;
      this.offset = offset;
      setOffsetIsSet(true);
      this.limit = limit;
      setLimitIsSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getUsers_args(getUsers_args other) {
      __isset_bitfield = other.__isset_bitfield;
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      this.offset = other.offset;
      this.limit = other.limit;
    }

    public getUsers_args deepCopy() {
      return new getUsers_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      setOffsetIsSet(false);
      this.offset = 0;
      setLimitIsSet(false);
      this.limit = 0;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getUsers_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public int getOffset() {
      return this.offset;
    }

    public getUsers_args setOffset(int offset) {
      this.offset = offset;
      setOffsetIsSet(true);
      return this;
    }

    public void unsetOffset() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    /** Returns true if field offset is set (has been assigned a value) and false otherwise */
    public boolean isSetOffset() {
      return EncodingUtils.testBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    public void setOffsetIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __OFFSET_ISSET_ID, value);
    }

    public int getLimit() {
      return this.limit;
    }

    public getUsers_args setLimit(int limit) {
      this.limit = limit;
      setLimitIsSet(true);
      return this;
    }

    public void unsetLimit() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    /** Returns true if field limit is set (has been assigned a value) and false otherwise */
    public boolean isSetLimit() {
      return EncodingUtils.testBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    public void setLimitIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __LIMIT_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case OFFSET:
        if (value == null) {
          unsetOffset();
        } else {
          setOffset((Integer)value);
        }
        break;

      case LIMIT:
        if (value == null) {
          unsetLimit();
        } else {
          setLimit((Integer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case OFFSET:
        return getOffset();

      case LIMIT:
        return getLimit();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case OFFSET:
        return isSetOffset();
      case LIMIT:
        return isSetLimit();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getUsers_args)
        return this.equals((getUsers_args)that);
      return false;
    }

    public boolean equals(getUsers_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_offset = true;
      boolean that_present_offset = true;
      if (this_present_offset || that_present_offset) {
        if (!(this_present_offset && that_present_offset))
          return false;
        if (this.offset != that.offset)
          return false;
      }

      boolean this_present_limit = true;
      boolean that_present_limit = true;
      if (this_present_limit || that_present_limit) {
        if (!(this_present_limit && that_present_limit))
          return false;
        if (this.limit != that.limit)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_offset = true;
      list.add(present_offset);
      if (present_offset)
        list.add(offset);

      boolean present_limit = true;
      list.add(present_limit);
      if (present_limit)
        list.add(limit);

      return list.hashCode();
    }

    @Override
    public int compareTo(getUsers_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetOffset()).compareTo(other.isSetOffset());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetOffset()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.offset, other.offset);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetLimit()).compareTo(other.isSetLimit());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetLimit()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.limit, other.limit);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getUsers_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("offset:");
      sb.append(this.offset);
      first = false;
      if (!first) sb.append(", ");
      sb.append("limit:");
      sb.append(this.limit);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      // alas, we cannot check 'offset' because it's a primitive and you chose the non-beans generator.
      // alas, we cannot check 'limit' because it's a primitive and you chose the non-beans generator.
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getUsers_argsStandardSchemeFactory implements SchemeFactory {
      public getUsers_argsStandardScheme getScheme() {
        return new getUsers_argsStandardScheme();
      }
    }

    private static class getUsers_argsStandardScheme extends StandardScheme<getUsers_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getUsers_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // OFFSET
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.offset = iprot.readI32();
                struct.setOffsetIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // LIMIT
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.limit = iprot.readI32();
                struct.setLimitIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        if (!struct.isSetOffset()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'offset' was not found in serialized data! Struct: " + toString());
        }
        if (!struct.isSetLimit()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'limit' was not found in serialized data! Struct: " + toString());
        }
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getUsers_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldBegin(OFFSET_FIELD_DESC);
        oprot.writeI32(struct.offset);
        oprot.writeFieldEnd();
        oprot.writeFieldBegin(LIMIT_FIELD_DESC);
        oprot.writeI32(struct.limit);
        oprot.writeFieldEnd();
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getUsers_argsTupleSchemeFactory implements SchemeFactory {
      public getUsers_argsTupleScheme getScheme() {
        return new getUsers_argsTupleScheme();
      }
    }

    private static class getUsers_argsTupleScheme extends TupleScheme<getUsers_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getUsers_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeI32(struct.offset);
        oprot.writeI32(struct.limit);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getUsers_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.offset = iprot.readI32();
        struct.setOffsetIsSet(true);
        struct.limit = iprot.readI32();
        struct.setLimitIsSet(true);
      }
    }

  }

  public static class getUsers_result implements org.apache.thrift.TBase<getUsers_result, getUsers_result._Fields>, java.io.Serializable, Cloneable, Comparable<getUsers_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getUsers_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getUsers_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getUsers_resultTupleSchemeFactory());
    }

    public List<org.apache.airavata.sharing.registry.models.User> success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.User.class))));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getUsers_result.class, metaDataMap);
    }

    public getUsers_result() {
    }

    public getUsers_result(
      List<org.apache.airavata.sharing.registry.models.User> success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getUsers_result(getUsers_result other) {
      if (other.isSetSuccess()) {
        List<org.apache.airavata.sharing.registry.models.User> __this__success = new ArrayList<org.apache.airavata.sharing.registry.models.User>(other.success.size());
        for (org.apache.airavata.sharing.registry.models.User other_element : other.success) {
          __this__success.add(new org.apache.airavata.sharing.registry.models.User(other_element));
        }
        this.success = __this__success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getUsers_result deepCopy() {
      return new getUsers_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public int getSuccessSize() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<org.apache.airavata.sharing.registry.models.User> getSuccessIterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void addToSuccess(org.apache.airavata.sharing.registry.models.User elem) {
      if (this.success == null) {
        this.success = new ArrayList<org.apache.airavata.sharing.registry.models.User>();
      }
      this.success.add(elem);
    }

    public List<org.apache.airavata.sharing.registry.models.User> getSuccess() {
      return this.success;
    }

    public getUsers_result setSuccess(List<org.apache.airavata.sharing.registry.models.User> success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getUsers_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((List<org.apache.airavata.sharing.registry.models.User>)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getUsers_result)
        return this.equals((getUsers_result)that);
      return false;
    }

    public boolean equals(getUsers_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getUsers_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getUsers_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getUsers_resultStandardSchemeFactory implements SchemeFactory {
      public getUsers_resultStandardScheme getScheme() {
        return new getUsers_resultStandardScheme();
      }
    }

    private static class getUsers_resultStandardScheme extends StandardScheme<getUsers_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getUsers_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list8 = iprot.readListBegin();
                  struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.User>(_list8.size);
                  org.apache.airavata.sharing.registry.models.User _elem9;
                  for (int _i10 = 0; _i10 < _list8.size; ++_i10)
                  {
                    _elem9 = new org.apache.airavata.sharing.registry.models.User();
                    _elem9.read(iprot);
                    struct.success.add(_elem9);
                  }
                  iprot.readListEnd();
                }
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getUsers_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (org.apache.airavata.sharing.registry.models.User _iter11 : struct.success)
            {
              _iter11.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getUsers_resultTupleSchemeFactory implements SchemeFactory {
      public getUsers_resultTupleScheme getScheme() {
        return new getUsers_resultTupleScheme();
      }
    }

    private static class getUsers_resultTupleScheme extends TupleScheme<getUsers_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getUsers_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          {
            oprot.writeI32(struct.success.size());
            for (org.apache.airavata.sharing.registry.models.User _iter12 : struct.success)
            {
              _iter12.write(oprot);
            }
          }
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getUsers_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list13 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.User>(_list13.size);
            org.apache.airavata.sharing.registry.models.User _elem14;
            for (int _i15 = 0; _i15 < _list13.size; ++_i15)
            {
              _elem14 = new org.apache.airavata.sharing.registry.models.User();
              _elem14.read(iprot);
              struct.success.add(_elem14);
            }
          }
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class createGroup_args implements org.apache.thrift.TBase<createGroup_args, createGroup_args._Fields>, java.io.Serializable, Cloneable, Comparable<createGroup_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createGroup_args");

    private static final org.apache.thrift.protocol.TField GROUP_FIELD_DESC = new org.apache.thrift.protocol.TField("group", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new createGroup_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new createGroup_argsTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.UserGroup group; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      GROUP((short)1, "group");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // GROUP
            return GROUP;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.GROUP, new org.apache.thrift.meta_data.FieldMetaData("group", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.UserGroup.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createGroup_args.class, metaDataMap);
    }

    public createGroup_args() {
    }

    public createGroup_args(
      org.apache.airavata.sharing.registry.models.UserGroup group)
    {
      this();
      this.group = group;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public createGroup_args(createGroup_args other) {
      if (other.isSetGroup()) {
        this.group = new org.apache.airavata.sharing.registry.models.UserGroup(other.group);
      }
    }

    public createGroup_args deepCopy() {
      return new createGroup_args(this);
    }

    @Override
    public void clear() {
      this.group = null;
    }

    public org.apache.airavata.sharing.registry.models.UserGroup getGroup() {
      return this.group;
    }

    public createGroup_args setGroup(org.apache.airavata.sharing.registry.models.UserGroup group) {
      this.group = group;
      return this;
    }

    public void unsetGroup() {
      this.group = null;
    }

    /** Returns true if field group is set (has been assigned a value) and false otherwise */
    public boolean isSetGroup() {
      return this.group != null;
    }

    public void setGroupIsSet(boolean value) {
      if (!value) {
        this.group = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case GROUP:
        if (value == null) {
          unsetGroup();
        } else {
          setGroup((org.apache.airavata.sharing.registry.models.UserGroup)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case GROUP:
        return getGroup();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case GROUP:
        return isSetGroup();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof createGroup_args)
        return this.equals((createGroup_args)that);
      return false;
    }

    public boolean equals(createGroup_args that) {
      if (that == null)
        return false;

      boolean this_present_group = true && this.isSetGroup();
      boolean that_present_group = true && that.isSetGroup();
      if (this_present_group || that_present_group) {
        if (!(this_present_group && that_present_group))
          return false;
        if (!this.group.equals(that.group))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_group = true && (isSetGroup());
      list.add(present_group);
      if (present_group)
        list.add(group);

      return list.hashCode();
    }

    @Override
    public int compareTo(createGroup_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetGroup()).compareTo(other.isSetGroup());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetGroup()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.group, other.group);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("createGroup_args(");
      boolean first = true;

      sb.append("group:");
      if (this.group == null) {
        sb.append("null");
      } else {
        sb.append(this.group);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (group == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'group' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
      if (group != null) {
        group.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class createGroup_argsStandardSchemeFactory implements SchemeFactory {
      public createGroup_argsStandardScheme getScheme() {
        return new createGroup_argsStandardScheme();
      }
    }

    private static class createGroup_argsStandardScheme extends StandardScheme<createGroup_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, createGroup_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // GROUP
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.group = new org.apache.airavata.sharing.registry.models.UserGroup();
                struct.group.read(iprot);
                struct.setGroupIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, createGroup_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.group != null) {
          oprot.writeFieldBegin(GROUP_FIELD_DESC);
          struct.group.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class createGroup_argsTupleSchemeFactory implements SchemeFactory {
      public createGroup_argsTupleScheme getScheme() {
        return new createGroup_argsTupleScheme();
      }
    }

    private static class createGroup_argsTupleScheme extends TupleScheme<createGroup_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, createGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        struct.group.write(oprot);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, createGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.group = new org.apache.airavata.sharing.registry.models.UserGroup();
        struct.group.read(iprot);
        struct.setGroupIsSet(true);
      }
    }

  }

  public static class createGroup_result implements org.apache.thrift.TBase<createGroup_result, createGroup_result._Fields>, java.io.Serializable, Cloneable, Comparable<createGroup_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createGroup_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new createGroup_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new createGroup_resultTupleSchemeFactory());
    }

    public String success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createGroup_result.class, metaDataMap);
    }

    public createGroup_result() {
    }

    public createGroup_result(
      String success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public createGroup_result(createGroup_result other) {
      if (other.isSetSuccess()) {
        this.success = other.success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public createGroup_result deepCopy() {
      return new createGroup_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public String getSuccess() {
      return this.success;
    }

    public createGroup_result setSuccess(String success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public createGroup_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((String)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof createGroup_result)
        return this.equals((createGroup_result)that);
      return false;
    }

    public boolean equals(createGroup_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(createGroup_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("createGroup_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class createGroup_resultStandardSchemeFactory implements SchemeFactory {
      public createGroup_resultStandardScheme getScheme() {
        return new createGroup_resultStandardScheme();
      }
    }

    private static class createGroup_resultStandardScheme extends StandardScheme<createGroup_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, createGroup_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.success = iprot.readString();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, createGroup_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeString(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class createGroup_resultTupleSchemeFactory implements SchemeFactory {
      public createGroup_resultTupleScheme getScheme() {
        return new createGroup_resultTupleScheme();
      }
    }

    private static class createGroup_resultTupleScheme extends TupleScheme<createGroup_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, createGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeString(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, createGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readString();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class updateGroup_args implements org.apache.thrift.TBase<updateGroup_args, updateGroup_args._Fields>, java.io.Serializable, Cloneable, Comparable<updateGroup_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updateGroup_args");

    private static final org.apache.thrift.protocol.TField GROUP_FIELD_DESC = new org.apache.thrift.protocol.TField("group", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updateGroup_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updateGroup_argsTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.UserGroup group; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      GROUP((short)1, "group");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // GROUP
            return GROUP;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.GROUP, new org.apache.thrift.meta_data.FieldMetaData("group", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.UserGroup.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updateGroup_args.class, metaDataMap);
    }

    public updateGroup_args() {
    }

    public updateGroup_args(
      org.apache.airavata.sharing.registry.models.UserGroup group)
    {
      this();
      this.group = group;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updateGroup_args(updateGroup_args other) {
      if (other.isSetGroup()) {
        this.group = new org.apache.airavata.sharing.registry.models.UserGroup(other.group);
      }
    }

    public updateGroup_args deepCopy() {
      return new updateGroup_args(this);
    }

    @Override
    public void clear() {
      this.group = null;
    }

    public org.apache.airavata.sharing.registry.models.UserGroup getGroup() {
      return this.group;
    }

    public updateGroup_args setGroup(org.apache.airavata.sharing.registry.models.UserGroup group) {
      this.group = group;
      return this;
    }

    public void unsetGroup() {
      this.group = null;
    }

    /** Returns true if field group is set (has been assigned a value) and false otherwise */
    public boolean isSetGroup() {
      return this.group != null;
    }

    public void setGroupIsSet(boolean value) {
      if (!value) {
        this.group = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case GROUP:
        if (value == null) {
          unsetGroup();
        } else {
          setGroup((org.apache.airavata.sharing.registry.models.UserGroup)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case GROUP:
        return getGroup();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case GROUP:
        return isSetGroup();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updateGroup_args)
        return this.equals((updateGroup_args)that);
      return false;
    }

    public boolean equals(updateGroup_args that) {
      if (that == null)
        return false;

      boolean this_present_group = true && this.isSetGroup();
      boolean that_present_group = true && that.isSetGroup();
      if (this_present_group || that_present_group) {
        if (!(this_present_group && that_present_group))
          return false;
        if (!this.group.equals(that.group))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_group = true && (isSetGroup());
      list.add(present_group);
      if (present_group)
        list.add(group);

      return list.hashCode();
    }

    @Override
    public int compareTo(updateGroup_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetGroup()).compareTo(other.isSetGroup());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetGroup()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.group, other.group);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updateGroup_args(");
      boolean first = true;

      sb.append("group:");
      if (this.group == null) {
        sb.append("null");
      } else {
        sb.append(this.group);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (group == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'group' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
      if (group != null) {
        group.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updateGroup_argsStandardSchemeFactory implements SchemeFactory {
      public updateGroup_argsStandardScheme getScheme() {
        return new updateGroup_argsStandardScheme();
      }
    }

    private static class updateGroup_argsStandardScheme extends StandardScheme<updateGroup_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updateGroup_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // GROUP
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.group = new org.apache.airavata.sharing.registry.models.UserGroup();
                struct.group.read(iprot);
                struct.setGroupIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updateGroup_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.group != null) {
          oprot.writeFieldBegin(GROUP_FIELD_DESC);
          struct.group.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updateGroup_argsTupleSchemeFactory implements SchemeFactory {
      public updateGroup_argsTupleScheme getScheme() {
        return new updateGroup_argsTupleScheme();
      }
    }

    private static class updateGroup_argsTupleScheme extends TupleScheme<updateGroup_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updateGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        struct.group.write(oprot);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updateGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.group = new org.apache.airavata.sharing.registry.models.UserGroup();
        struct.group.read(iprot);
        struct.setGroupIsSet(true);
      }
    }

  }

  public static class updateGroup_result implements org.apache.thrift.TBase<updateGroup_result, updateGroup_result._Fields>, java.io.Serializable, Cloneable, Comparable<updateGroup_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updateGroup_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updateGroup_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updateGroup_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updateGroup_result.class, metaDataMap);
    }

    public updateGroup_result() {
    }

    public updateGroup_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updateGroup_result(updateGroup_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public updateGroup_result deepCopy() {
      return new updateGroup_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public updateGroup_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public updateGroup_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updateGroup_result)
        return this.equals((updateGroup_result)that);
      return false;
    }

    public boolean equals(updateGroup_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(updateGroup_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updateGroup_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updateGroup_resultStandardSchemeFactory implements SchemeFactory {
      public updateGroup_resultStandardScheme getScheme() {
        return new updateGroup_resultStandardScheme();
      }
    }

    private static class updateGroup_resultStandardScheme extends StandardScheme<updateGroup_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updateGroup_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updateGroup_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updateGroup_resultTupleSchemeFactory implements SchemeFactory {
      public updateGroup_resultTupleScheme getScheme() {
        return new updateGroup_resultTupleScheme();
      }
    }

    private static class updateGroup_resultTupleScheme extends TupleScheme<updateGroup_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updateGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updateGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class isGroupExists_args implements org.apache.thrift.TBase<isGroupExists_args, isGroupExists_args._Fields>, java.io.Serializable, Cloneable, Comparable<isGroupExists_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("isGroupExists_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField GROUP_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("groupId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new isGroupExists_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new isGroupExists_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String groupId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      GROUP_ID((short)2, "groupId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // GROUP_ID
            return GROUP_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.GROUP_ID, new org.apache.thrift.meta_data.FieldMetaData("groupId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(isGroupExists_args.class, metaDataMap);
    }

    public isGroupExists_args() {
    }

    public isGroupExists_args(
      String domainId,
      String groupId)
    {
      this();
      this.domainId = domainId;
      this.groupId = groupId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public isGroupExists_args(isGroupExists_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetGroupId()) {
        this.groupId = other.groupId;
      }
    }

    public isGroupExists_args deepCopy() {
      return new isGroupExists_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.groupId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public isGroupExists_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getGroupId() {
      return this.groupId;
    }

    public isGroupExists_args setGroupId(String groupId) {
      this.groupId = groupId;
      return this;
    }

    public void unsetGroupId() {
      this.groupId = null;
    }

    /** Returns true if field groupId is set (has been assigned a value) and false otherwise */
    public boolean isSetGroupId() {
      return this.groupId != null;
    }

    public void setGroupIdIsSet(boolean value) {
      if (!value) {
        this.groupId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case GROUP_ID:
        if (value == null) {
          unsetGroupId();
        } else {
          setGroupId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case GROUP_ID:
        return getGroupId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case GROUP_ID:
        return isSetGroupId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof isGroupExists_args)
        return this.equals((isGroupExists_args)that);
      return false;
    }

    public boolean equals(isGroupExists_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_groupId = true && this.isSetGroupId();
      boolean that_present_groupId = true && that.isSetGroupId();
      if (this_present_groupId || that_present_groupId) {
        if (!(this_present_groupId && that_present_groupId))
          return false;
        if (!this.groupId.equals(that.groupId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_groupId = true && (isSetGroupId());
      list.add(present_groupId);
      if (present_groupId)
        list.add(groupId);

      return list.hashCode();
    }

    @Override
    public int compareTo(isGroupExists_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetGroupId()).compareTo(other.isSetGroupId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetGroupId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.groupId, other.groupId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("isGroupExists_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("groupId:");
      if (this.groupId == null) {
        sb.append("null");
      } else {
        sb.append(this.groupId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (groupId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'groupId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class isGroupExists_argsStandardSchemeFactory implements SchemeFactory {
      public isGroupExists_argsStandardScheme getScheme() {
        return new isGroupExists_argsStandardScheme();
      }
    }

    private static class isGroupExists_argsStandardScheme extends StandardScheme<isGroupExists_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, isGroupExists_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // GROUP_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.groupId = iprot.readString();
                struct.setGroupIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, isGroupExists_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.groupId != null) {
          oprot.writeFieldBegin(GROUP_ID_FIELD_DESC);
          oprot.writeString(struct.groupId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class isGroupExists_argsTupleSchemeFactory implements SchemeFactory {
      public isGroupExists_argsTupleScheme getScheme() {
        return new isGroupExists_argsTupleScheme();
      }
    }

    private static class isGroupExists_argsTupleScheme extends TupleScheme<isGroupExists_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, isGroupExists_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.groupId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, isGroupExists_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.groupId = iprot.readString();
        struct.setGroupIdIsSet(true);
      }
    }

  }

  public static class isGroupExists_result implements org.apache.thrift.TBase<isGroupExists_result, isGroupExists_result._Fields>, java.io.Serializable, Cloneable, Comparable<isGroupExists_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("isGroupExists_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new isGroupExists_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new isGroupExists_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(isGroupExists_result.class, metaDataMap);
    }

    public isGroupExists_result() {
    }

    public isGroupExists_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public isGroupExists_result(isGroupExists_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public isGroupExists_result deepCopy() {
      return new isGroupExists_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public isGroupExists_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public isGroupExists_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof isGroupExists_result)
        return this.equals((isGroupExists_result)that);
      return false;
    }

    public boolean equals(isGroupExists_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(isGroupExists_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("isGroupExists_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class isGroupExists_resultStandardSchemeFactory implements SchemeFactory {
      public isGroupExists_resultStandardScheme getScheme() {
        return new isGroupExists_resultStandardScheme();
      }
    }

    private static class isGroupExists_resultStandardScheme extends StandardScheme<isGroupExists_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, isGroupExists_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, isGroupExists_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class isGroupExists_resultTupleSchemeFactory implements SchemeFactory {
      public isGroupExists_resultTupleScheme getScheme() {
        return new isGroupExists_resultTupleScheme();
      }
    }

    private static class isGroupExists_resultTupleScheme extends TupleScheme<isGroupExists_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, isGroupExists_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, isGroupExists_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class deleteGroup_args implements org.apache.thrift.TBase<deleteGroup_args, deleteGroup_args._Fields>, java.io.Serializable, Cloneable, Comparable<deleteGroup_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deleteGroup_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField GROUP_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("groupId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deleteGroup_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deleteGroup_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String groupId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      GROUP_ID((short)2, "groupId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // GROUP_ID
            return GROUP_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.GROUP_ID, new org.apache.thrift.meta_data.FieldMetaData("groupId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deleteGroup_args.class, metaDataMap);
    }

    public deleteGroup_args() {
    }

    public deleteGroup_args(
      String domainId,
      String groupId)
    {
      this();
      this.domainId = domainId;
      this.groupId = groupId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deleteGroup_args(deleteGroup_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetGroupId()) {
        this.groupId = other.groupId;
      }
    }

    public deleteGroup_args deepCopy() {
      return new deleteGroup_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.groupId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public deleteGroup_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getGroupId() {
      return this.groupId;
    }

    public deleteGroup_args setGroupId(String groupId) {
      this.groupId = groupId;
      return this;
    }

    public void unsetGroupId() {
      this.groupId = null;
    }

    /** Returns true if field groupId is set (has been assigned a value) and false otherwise */
    public boolean isSetGroupId() {
      return this.groupId != null;
    }

    public void setGroupIdIsSet(boolean value) {
      if (!value) {
        this.groupId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case GROUP_ID:
        if (value == null) {
          unsetGroupId();
        } else {
          setGroupId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case GROUP_ID:
        return getGroupId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case GROUP_ID:
        return isSetGroupId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deleteGroup_args)
        return this.equals((deleteGroup_args)that);
      return false;
    }

    public boolean equals(deleteGroup_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_groupId = true && this.isSetGroupId();
      boolean that_present_groupId = true && that.isSetGroupId();
      if (this_present_groupId || that_present_groupId) {
        if (!(this_present_groupId && that_present_groupId))
          return false;
        if (!this.groupId.equals(that.groupId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_groupId = true && (isSetGroupId());
      list.add(present_groupId);
      if (present_groupId)
        list.add(groupId);

      return list.hashCode();
    }

    @Override
    public int compareTo(deleteGroup_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetGroupId()).compareTo(other.isSetGroupId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetGroupId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.groupId, other.groupId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deleteGroup_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("groupId:");
      if (this.groupId == null) {
        sb.append("null");
      } else {
        sb.append(this.groupId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (groupId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'groupId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deleteGroup_argsStandardSchemeFactory implements SchemeFactory {
      public deleteGroup_argsStandardScheme getScheme() {
        return new deleteGroup_argsStandardScheme();
      }
    }

    private static class deleteGroup_argsStandardScheme extends StandardScheme<deleteGroup_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deleteGroup_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // GROUP_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.groupId = iprot.readString();
                struct.setGroupIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deleteGroup_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.groupId != null) {
          oprot.writeFieldBegin(GROUP_ID_FIELD_DESC);
          oprot.writeString(struct.groupId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deleteGroup_argsTupleSchemeFactory implements SchemeFactory {
      public deleteGroup_argsTupleScheme getScheme() {
        return new deleteGroup_argsTupleScheme();
      }
    }

    private static class deleteGroup_argsTupleScheme extends TupleScheme<deleteGroup_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deleteGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.groupId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deleteGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.groupId = iprot.readString();
        struct.setGroupIdIsSet(true);
      }
    }

  }

  public static class deleteGroup_result implements org.apache.thrift.TBase<deleteGroup_result, deleteGroup_result._Fields>, java.io.Serializable, Cloneable, Comparable<deleteGroup_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deleteGroup_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deleteGroup_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deleteGroup_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deleteGroup_result.class, metaDataMap);
    }

    public deleteGroup_result() {
    }

    public deleteGroup_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deleteGroup_result(deleteGroup_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public deleteGroup_result deepCopy() {
      return new deleteGroup_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public deleteGroup_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public deleteGroup_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deleteGroup_result)
        return this.equals((deleteGroup_result)that);
      return false;
    }

    public boolean equals(deleteGroup_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(deleteGroup_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deleteGroup_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deleteGroup_resultStandardSchemeFactory implements SchemeFactory {
      public deleteGroup_resultStandardScheme getScheme() {
        return new deleteGroup_resultStandardScheme();
      }
    }

    private static class deleteGroup_resultStandardScheme extends StandardScheme<deleteGroup_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deleteGroup_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deleteGroup_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deleteGroup_resultTupleSchemeFactory implements SchemeFactory {
      public deleteGroup_resultTupleScheme getScheme() {
        return new deleteGroup_resultTupleScheme();
      }
    }

    private static class deleteGroup_resultTupleScheme extends TupleScheme<deleteGroup_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deleteGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deleteGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getGroup_args implements org.apache.thrift.TBase<getGroup_args, getGroup_args._Fields>, java.io.Serializable, Cloneable, Comparable<getGroup_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getGroup_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField GROUP_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("groupId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getGroup_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getGroup_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String groupId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      GROUP_ID((short)2, "groupId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // GROUP_ID
            return GROUP_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.GROUP_ID, new org.apache.thrift.meta_data.FieldMetaData("groupId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getGroup_args.class, metaDataMap);
    }

    public getGroup_args() {
    }

    public getGroup_args(
      String domainId,
      String groupId)
    {
      this();
      this.domainId = domainId;
      this.groupId = groupId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getGroup_args(getGroup_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetGroupId()) {
        this.groupId = other.groupId;
      }
    }

    public getGroup_args deepCopy() {
      return new getGroup_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.groupId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getGroup_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getGroupId() {
      return this.groupId;
    }

    public getGroup_args setGroupId(String groupId) {
      this.groupId = groupId;
      return this;
    }

    public void unsetGroupId() {
      this.groupId = null;
    }

    /** Returns true if field groupId is set (has been assigned a value) and false otherwise */
    public boolean isSetGroupId() {
      return this.groupId != null;
    }

    public void setGroupIdIsSet(boolean value) {
      if (!value) {
        this.groupId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case GROUP_ID:
        if (value == null) {
          unsetGroupId();
        } else {
          setGroupId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case GROUP_ID:
        return getGroupId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case GROUP_ID:
        return isSetGroupId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getGroup_args)
        return this.equals((getGroup_args)that);
      return false;
    }

    public boolean equals(getGroup_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_groupId = true && this.isSetGroupId();
      boolean that_present_groupId = true && that.isSetGroupId();
      if (this_present_groupId || that_present_groupId) {
        if (!(this_present_groupId && that_present_groupId))
          return false;
        if (!this.groupId.equals(that.groupId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_groupId = true && (isSetGroupId());
      list.add(present_groupId);
      if (present_groupId)
        list.add(groupId);

      return list.hashCode();
    }

    @Override
    public int compareTo(getGroup_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetGroupId()).compareTo(other.isSetGroupId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetGroupId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.groupId, other.groupId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getGroup_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("groupId:");
      if (this.groupId == null) {
        sb.append("null");
      } else {
        sb.append(this.groupId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (groupId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'groupId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getGroup_argsStandardSchemeFactory implements SchemeFactory {
      public getGroup_argsStandardScheme getScheme() {
        return new getGroup_argsStandardScheme();
      }
    }

    private static class getGroup_argsStandardScheme extends StandardScheme<getGroup_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getGroup_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // GROUP_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.groupId = iprot.readString();
                struct.setGroupIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getGroup_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.groupId != null) {
          oprot.writeFieldBegin(GROUP_ID_FIELD_DESC);
          oprot.writeString(struct.groupId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getGroup_argsTupleSchemeFactory implements SchemeFactory {
      public getGroup_argsTupleScheme getScheme() {
        return new getGroup_argsTupleScheme();
      }
    }

    private static class getGroup_argsTupleScheme extends TupleScheme<getGroup_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.groupId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.groupId = iprot.readString();
        struct.setGroupIdIsSet(true);
      }
    }

  }

  public static class getGroup_result implements org.apache.thrift.TBase<getGroup_result, getGroup_result._Fields>, java.io.Serializable, Cloneable, Comparable<getGroup_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getGroup_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getGroup_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getGroup_resultTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.UserGroup success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.UserGroup.class)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getGroup_result.class, metaDataMap);
    }

    public getGroup_result() {
    }

    public getGroup_result(
      org.apache.airavata.sharing.registry.models.UserGroup success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getGroup_result(getGroup_result other) {
      if (other.isSetSuccess()) {
        this.success = new org.apache.airavata.sharing.registry.models.UserGroup(other.success);
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getGroup_result deepCopy() {
      return new getGroup_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public org.apache.airavata.sharing.registry.models.UserGroup getSuccess() {
      return this.success;
    }

    public getGroup_result setSuccess(org.apache.airavata.sharing.registry.models.UserGroup success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getGroup_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((org.apache.airavata.sharing.registry.models.UserGroup)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getGroup_result)
        return this.equals((getGroup_result)that);
      return false;
    }

    public boolean equals(getGroup_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getGroup_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getGroup_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getGroup_resultStandardSchemeFactory implements SchemeFactory {
      public getGroup_resultStandardScheme getScheme() {
        return new getGroup_resultStandardScheme();
      }
    }

    private static class getGroup_resultStandardScheme extends StandardScheme<getGroup_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getGroup_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new org.apache.airavata.sharing.registry.models.UserGroup();
                struct.success.read(iprot);
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getGroup_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getGroup_resultTupleSchemeFactory implements SchemeFactory {
      public getGroup_resultTupleScheme getScheme() {
        return new getGroup_resultTupleScheme();
      }
    }

    private static class getGroup_resultTupleScheme extends TupleScheme<getGroup_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          struct.success.write(oprot);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = new org.apache.airavata.sharing.registry.models.UserGroup();
          struct.success.read(iprot);
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getGroups_args implements org.apache.thrift.TBase<getGroups_args, getGroups_args._Fields>, java.io.Serializable, Cloneable, Comparable<getGroups_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getGroups_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField OFFSET_FIELD_DESC = new org.apache.thrift.protocol.TField("offset", org.apache.thrift.protocol.TType.I32, (short)2);
    private static final org.apache.thrift.protocol.TField LIMIT_FIELD_DESC = new org.apache.thrift.protocol.TField("limit", org.apache.thrift.protocol.TType.I32, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getGroups_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getGroups_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public int offset; // required
    public int limit; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      OFFSET((short)2, "offset"),
      LIMIT((short)3, "limit");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // OFFSET
            return OFFSET;
          case 3: // LIMIT
            return LIMIT;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __OFFSET_ISSET_ID = 0;
    private static final int __LIMIT_ISSET_ID = 1;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.OFFSET, new org.apache.thrift.meta_data.FieldMetaData("offset", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      tmpMap.put(_Fields.LIMIT, new org.apache.thrift.meta_data.FieldMetaData("limit", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getGroups_args.class, metaDataMap);
    }

    public getGroups_args() {
    }

    public getGroups_args(
      String domainId,
      int offset,
      int limit)
    {
      this();
      this.domainId = domainId;
      this.offset = offset;
      setOffsetIsSet(true);
      this.limit = limit;
      setLimitIsSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getGroups_args(getGroups_args other) {
      __isset_bitfield = other.__isset_bitfield;
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      this.offset = other.offset;
      this.limit = other.limit;
    }

    public getGroups_args deepCopy() {
      return new getGroups_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      setOffsetIsSet(false);
      this.offset = 0;
      setLimitIsSet(false);
      this.limit = 0;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getGroups_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public int getOffset() {
      return this.offset;
    }

    public getGroups_args setOffset(int offset) {
      this.offset = offset;
      setOffsetIsSet(true);
      return this;
    }

    public void unsetOffset() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    /** Returns true if field offset is set (has been assigned a value) and false otherwise */
    public boolean isSetOffset() {
      return EncodingUtils.testBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    public void setOffsetIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __OFFSET_ISSET_ID, value);
    }

    public int getLimit() {
      return this.limit;
    }

    public getGroups_args setLimit(int limit) {
      this.limit = limit;
      setLimitIsSet(true);
      return this;
    }

    public void unsetLimit() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    /** Returns true if field limit is set (has been assigned a value) and false otherwise */
    public boolean isSetLimit() {
      return EncodingUtils.testBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    public void setLimitIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __LIMIT_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case OFFSET:
        if (value == null) {
          unsetOffset();
        } else {
          setOffset((Integer)value);
        }
        break;

      case LIMIT:
        if (value == null) {
          unsetLimit();
        } else {
          setLimit((Integer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case OFFSET:
        return getOffset();

      case LIMIT:
        return getLimit();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case OFFSET:
        return isSetOffset();
      case LIMIT:
        return isSetLimit();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getGroups_args)
        return this.equals((getGroups_args)that);
      return false;
    }

    public boolean equals(getGroups_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_offset = true;
      boolean that_present_offset = true;
      if (this_present_offset || that_present_offset) {
        if (!(this_present_offset && that_present_offset))
          return false;
        if (this.offset != that.offset)
          return false;
      }

      boolean this_present_limit = true;
      boolean that_present_limit = true;
      if (this_present_limit || that_present_limit) {
        if (!(this_present_limit && that_present_limit))
          return false;
        if (this.limit != that.limit)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_offset = true;
      list.add(present_offset);
      if (present_offset)
        list.add(offset);

      boolean present_limit = true;
      list.add(present_limit);
      if (present_limit)
        list.add(limit);

      return list.hashCode();
    }

    @Override
    public int compareTo(getGroups_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetOffset()).compareTo(other.isSetOffset());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetOffset()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.offset, other.offset);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetLimit()).compareTo(other.isSetLimit());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetLimit()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.limit, other.limit);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getGroups_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("offset:");
      sb.append(this.offset);
      first = false;
      if (!first) sb.append(", ");
      sb.append("limit:");
      sb.append(this.limit);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      // alas, we cannot check 'offset' because it's a primitive and you chose the non-beans generator.
      // alas, we cannot check 'limit' because it's a primitive and you chose the non-beans generator.
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getGroups_argsStandardSchemeFactory implements SchemeFactory {
      public getGroups_argsStandardScheme getScheme() {
        return new getGroups_argsStandardScheme();
      }
    }

    private static class getGroups_argsStandardScheme extends StandardScheme<getGroups_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getGroups_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // OFFSET
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.offset = iprot.readI32();
                struct.setOffsetIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // LIMIT
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.limit = iprot.readI32();
                struct.setLimitIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        if (!struct.isSetOffset()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'offset' was not found in serialized data! Struct: " + toString());
        }
        if (!struct.isSetLimit()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'limit' was not found in serialized data! Struct: " + toString());
        }
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getGroups_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldBegin(OFFSET_FIELD_DESC);
        oprot.writeI32(struct.offset);
        oprot.writeFieldEnd();
        oprot.writeFieldBegin(LIMIT_FIELD_DESC);
        oprot.writeI32(struct.limit);
        oprot.writeFieldEnd();
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getGroups_argsTupleSchemeFactory implements SchemeFactory {
      public getGroups_argsTupleScheme getScheme() {
        return new getGroups_argsTupleScheme();
      }
    }

    private static class getGroups_argsTupleScheme extends TupleScheme<getGroups_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getGroups_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeI32(struct.offset);
        oprot.writeI32(struct.limit);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getGroups_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.offset = iprot.readI32();
        struct.setOffsetIsSet(true);
        struct.limit = iprot.readI32();
        struct.setLimitIsSet(true);
      }
    }

  }

  public static class getGroups_result implements org.apache.thrift.TBase<getGroups_result, getGroups_result._Fields>, java.io.Serializable, Cloneable, Comparable<getGroups_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getGroups_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getGroups_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getGroups_resultTupleSchemeFactory());
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> success; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.UserGroup.class))));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getGroups_result.class, metaDataMap);
    }

    public getGroups_result() {
    }

    public getGroups_result(
      List<org.apache.airavata.sharing.registry.models.UserGroup> success)
    {
      this();
      this.success = success;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getGroups_result(getGroups_result other) {
      if (other.isSetSuccess()) {
        List<org.apache.airavata.sharing.registry.models.UserGroup> __this__success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>(other.success.size());
        for (org.apache.airavata.sharing.registry.models.UserGroup other_element : other.success) {
          __this__success.add(new org.apache.airavata.sharing.registry.models.UserGroup(other_element));
        }
        this.success = __this__success;
      }
    }

    public getGroups_result deepCopy() {
      return new getGroups_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
    }

    public int getSuccessSize() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<org.apache.airavata.sharing.registry.models.UserGroup> getSuccessIterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void addToSuccess(org.apache.airavata.sharing.registry.models.UserGroup elem) {
      if (this.success == null) {
        this.success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>();
      }
      this.success.add(elem);
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> getSuccess() {
      return this.success;
    }

    public getGroups_result setSuccess(List<org.apache.airavata.sharing.registry.models.UserGroup> success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((List<org.apache.airavata.sharing.registry.models.UserGroup>)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getGroups_result)
        return this.equals((getGroups_result)that);
      return false;
    }

    public boolean equals(getGroups_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      return list.hashCode();
    }

    @Override
    public int compareTo(getGroups_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getGroups_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getGroups_resultStandardSchemeFactory implements SchemeFactory {
      public getGroups_resultStandardScheme getScheme() {
        return new getGroups_resultStandardScheme();
      }
    }

    private static class getGroups_resultStandardScheme extends StandardScheme<getGroups_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getGroups_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list16 = iprot.readListBegin();
                  struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>(_list16.size);
                  org.apache.airavata.sharing.registry.models.UserGroup _elem17;
                  for (int _i18 = 0; _i18 < _list16.size; ++_i18)
                  {
                    _elem17 = new org.apache.airavata.sharing.registry.models.UserGroup();
                    _elem17.read(iprot);
                    struct.success.add(_elem17);
                  }
                  iprot.readListEnd();
                }
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getGroups_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (org.apache.airavata.sharing.registry.models.UserGroup _iter19 : struct.success)
            {
              _iter19.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getGroups_resultTupleSchemeFactory implements SchemeFactory {
      public getGroups_resultTupleScheme getScheme() {
        return new getGroups_resultTupleScheme();
      }
    }

    private static class getGroups_resultTupleScheme extends TupleScheme<getGroups_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getGroups_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.isSetSuccess()) {
          {
            oprot.writeI32(struct.success.size());
            for (org.apache.airavata.sharing.registry.models.UserGroup _iter20 : struct.success)
            {
              _iter20.write(oprot);
            }
          }
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getGroups_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list21 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>(_list21.size);
            org.apache.airavata.sharing.registry.models.UserGroup _elem22;
            for (int _i23 = 0; _i23 < _list21.size; ++_i23)
            {
              _elem22 = new org.apache.airavata.sharing.registry.models.UserGroup();
              _elem22.read(iprot);
              struct.success.add(_elem22);
            }
          }
          struct.setSuccessIsSet(true);
        }
      }
    }

  }

  public static class addUsersToGroup_args implements org.apache.thrift.TBase<addUsersToGroup_args, addUsersToGroup_args._Fields>, java.io.Serializable, Cloneable, Comparable<addUsersToGroup_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("addUsersToGroup_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField USER_IDS_FIELD_DESC = new org.apache.thrift.protocol.TField("userIds", org.apache.thrift.protocol.TType.LIST, (short)2);
    private static final org.apache.thrift.protocol.TField GROUP_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("groupId", org.apache.thrift.protocol.TType.STRING, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new addUsersToGroup_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new addUsersToGroup_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public List<String> userIds; // required
    public String groupId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      USER_IDS((short)2, "userIds"),
      GROUP_ID((short)3, "groupId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // USER_IDS
            return USER_IDS;
          case 3: // GROUP_ID
            return GROUP_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.USER_IDS, new org.apache.thrift.meta_data.FieldMetaData("userIds", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
      tmpMap.put(_Fields.GROUP_ID, new org.apache.thrift.meta_data.FieldMetaData("groupId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(addUsersToGroup_args.class, metaDataMap);
    }

    public addUsersToGroup_args() {
    }

    public addUsersToGroup_args(
      String domainId,
      List<String> userIds,
      String groupId)
    {
      this();
      this.domainId = domainId;
      this.userIds = userIds;
      this.groupId = groupId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public addUsersToGroup_args(addUsersToGroup_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetUserIds()) {
        List<String> __this__userIds = new ArrayList<String>(other.userIds);
        this.userIds = __this__userIds;
      }
      if (other.isSetGroupId()) {
        this.groupId = other.groupId;
      }
    }

    public addUsersToGroup_args deepCopy() {
      return new addUsersToGroup_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.userIds = null;
      this.groupId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public addUsersToGroup_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public int getUserIdsSize() {
      return (this.userIds == null) ? 0 : this.userIds.size();
    }

    public java.util.Iterator<String> getUserIdsIterator() {
      return (this.userIds == null) ? null : this.userIds.iterator();
    }

    public void addToUserIds(String elem) {
      if (this.userIds == null) {
        this.userIds = new ArrayList<String>();
      }
      this.userIds.add(elem);
    }

    public List<String> getUserIds() {
      return this.userIds;
    }

    public addUsersToGroup_args setUserIds(List<String> userIds) {
      this.userIds = userIds;
      return this;
    }

    public void unsetUserIds() {
      this.userIds = null;
    }

    /** Returns true if field userIds is set (has been assigned a value) and false otherwise */
    public boolean isSetUserIds() {
      return this.userIds != null;
    }

    public void setUserIdsIsSet(boolean value) {
      if (!value) {
        this.userIds = null;
      }
    }

    public String getGroupId() {
      return this.groupId;
    }

    public addUsersToGroup_args setGroupId(String groupId) {
      this.groupId = groupId;
      return this;
    }

    public void unsetGroupId() {
      this.groupId = null;
    }

    /** Returns true if field groupId is set (has been assigned a value) and false otherwise */
    public boolean isSetGroupId() {
      return this.groupId != null;
    }

    public void setGroupIdIsSet(boolean value) {
      if (!value) {
        this.groupId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case USER_IDS:
        if (value == null) {
          unsetUserIds();
        } else {
          setUserIds((List<String>)value);
        }
        break;

      case GROUP_ID:
        if (value == null) {
          unsetGroupId();
        } else {
          setGroupId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case USER_IDS:
        return getUserIds();

      case GROUP_ID:
        return getGroupId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case USER_IDS:
        return isSetUserIds();
      case GROUP_ID:
        return isSetGroupId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof addUsersToGroup_args)
        return this.equals((addUsersToGroup_args)that);
      return false;
    }

    public boolean equals(addUsersToGroup_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_userIds = true && this.isSetUserIds();
      boolean that_present_userIds = true && that.isSetUserIds();
      if (this_present_userIds || that_present_userIds) {
        if (!(this_present_userIds && that_present_userIds))
          return false;
        if (!this.userIds.equals(that.userIds))
          return false;
      }

      boolean this_present_groupId = true && this.isSetGroupId();
      boolean that_present_groupId = true && that.isSetGroupId();
      if (this_present_groupId || that_present_groupId) {
        if (!(this_present_groupId && that_present_groupId))
          return false;
        if (!this.groupId.equals(that.groupId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_userIds = true && (isSetUserIds());
      list.add(present_userIds);
      if (present_userIds)
        list.add(userIds);

      boolean present_groupId = true && (isSetGroupId());
      list.add(present_groupId);
      if (present_groupId)
        list.add(groupId);

      return list.hashCode();
    }

    @Override
    public int compareTo(addUsersToGroup_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetUserIds()).compareTo(other.isSetUserIds());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetUserIds()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.userIds, other.userIds);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetGroupId()).compareTo(other.isSetGroupId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetGroupId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.groupId, other.groupId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("addUsersToGroup_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("userIds:");
      if (this.userIds == null) {
        sb.append("null");
      } else {
        sb.append(this.userIds);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("groupId:");
      if (this.groupId == null) {
        sb.append("null");
      } else {
        sb.append(this.groupId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (userIds == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'userIds' was not present! Struct: " + toString());
      }
      if (groupId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'groupId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class addUsersToGroup_argsStandardSchemeFactory implements SchemeFactory {
      public addUsersToGroup_argsStandardScheme getScheme() {
        return new addUsersToGroup_argsStandardScheme();
      }
    }

    private static class addUsersToGroup_argsStandardScheme extends StandardScheme<addUsersToGroup_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, addUsersToGroup_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // USER_IDS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list24 = iprot.readListBegin();
                  struct.userIds = new ArrayList<String>(_list24.size);
                  String _elem25;
                  for (int _i26 = 0; _i26 < _list24.size; ++_i26)
                  {
                    _elem25 = iprot.readString();
                    struct.userIds.add(_elem25);
                  }
                  iprot.readListEnd();
                }
                struct.setUserIdsIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // GROUP_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.groupId = iprot.readString();
                struct.setGroupIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, addUsersToGroup_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.userIds != null) {
          oprot.writeFieldBegin(USER_IDS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.userIds.size()));
            for (String _iter27 : struct.userIds)
            {
              oprot.writeString(_iter27);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.groupId != null) {
          oprot.writeFieldBegin(GROUP_ID_FIELD_DESC);
          oprot.writeString(struct.groupId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class addUsersToGroup_argsTupleSchemeFactory implements SchemeFactory {
      public addUsersToGroup_argsTupleScheme getScheme() {
        return new addUsersToGroup_argsTupleScheme();
      }
    }

    private static class addUsersToGroup_argsTupleScheme extends TupleScheme<addUsersToGroup_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, addUsersToGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        {
          oprot.writeI32(struct.userIds.size());
          for (String _iter28 : struct.userIds)
          {
            oprot.writeString(_iter28);
          }
        }
        oprot.writeString(struct.groupId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, addUsersToGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        {
          org.apache.thrift.protocol.TList _list29 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
          struct.userIds = new ArrayList<String>(_list29.size);
          String _elem30;
          for (int _i31 = 0; _i31 < _list29.size; ++_i31)
          {
            _elem30 = iprot.readString();
            struct.userIds.add(_elem30);
          }
        }
        struct.setUserIdsIsSet(true);
        struct.groupId = iprot.readString();
        struct.setGroupIdIsSet(true);
      }
    }

  }

  public static class addUsersToGroup_result implements org.apache.thrift.TBase<addUsersToGroup_result, addUsersToGroup_result._Fields>, java.io.Serializable, Cloneable, Comparable<addUsersToGroup_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("addUsersToGroup_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new addUsersToGroup_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new addUsersToGroup_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(addUsersToGroup_result.class, metaDataMap);
    }

    public addUsersToGroup_result() {
    }

    public addUsersToGroup_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public addUsersToGroup_result(addUsersToGroup_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public addUsersToGroup_result deepCopy() {
      return new addUsersToGroup_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public addUsersToGroup_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public addUsersToGroup_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof addUsersToGroup_result)
        return this.equals((addUsersToGroup_result)that);
      return false;
    }

    public boolean equals(addUsersToGroup_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(addUsersToGroup_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("addUsersToGroup_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class addUsersToGroup_resultStandardSchemeFactory implements SchemeFactory {
      public addUsersToGroup_resultStandardScheme getScheme() {
        return new addUsersToGroup_resultStandardScheme();
      }
    }

    private static class addUsersToGroup_resultStandardScheme extends StandardScheme<addUsersToGroup_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, addUsersToGroup_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, addUsersToGroup_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class addUsersToGroup_resultTupleSchemeFactory implements SchemeFactory {
      public addUsersToGroup_resultTupleScheme getScheme() {
        return new addUsersToGroup_resultTupleScheme();
      }
    }

    private static class addUsersToGroup_resultTupleScheme extends TupleScheme<addUsersToGroup_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, addUsersToGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, addUsersToGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class removeUsersFromGroup_args implements org.apache.thrift.TBase<removeUsersFromGroup_args, removeUsersFromGroup_args._Fields>, java.io.Serializable, Cloneable, Comparable<removeUsersFromGroup_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("removeUsersFromGroup_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField USER_IDS_FIELD_DESC = new org.apache.thrift.protocol.TField("userIds", org.apache.thrift.protocol.TType.LIST, (short)2);
    private static final org.apache.thrift.protocol.TField GROUP_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("groupId", org.apache.thrift.protocol.TType.STRING, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new removeUsersFromGroup_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new removeUsersFromGroup_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public List<String> userIds; // required
    public String groupId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      USER_IDS((short)2, "userIds"),
      GROUP_ID((short)3, "groupId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // USER_IDS
            return USER_IDS;
          case 3: // GROUP_ID
            return GROUP_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.USER_IDS, new org.apache.thrift.meta_data.FieldMetaData("userIds", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
      tmpMap.put(_Fields.GROUP_ID, new org.apache.thrift.meta_data.FieldMetaData("groupId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(removeUsersFromGroup_args.class, metaDataMap);
    }

    public removeUsersFromGroup_args() {
    }

    public removeUsersFromGroup_args(
      String domainId,
      List<String> userIds,
      String groupId)
    {
      this();
      this.domainId = domainId;
      this.userIds = userIds;
      this.groupId = groupId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public removeUsersFromGroup_args(removeUsersFromGroup_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetUserIds()) {
        List<String> __this__userIds = new ArrayList<String>(other.userIds);
        this.userIds = __this__userIds;
      }
      if (other.isSetGroupId()) {
        this.groupId = other.groupId;
      }
    }

    public removeUsersFromGroup_args deepCopy() {
      return new removeUsersFromGroup_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.userIds = null;
      this.groupId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public removeUsersFromGroup_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public int getUserIdsSize() {
      return (this.userIds == null) ? 0 : this.userIds.size();
    }

    public java.util.Iterator<String> getUserIdsIterator() {
      return (this.userIds == null) ? null : this.userIds.iterator();
    }

    public void addToUserIds(String elem) {
      if (this.userIds == null) {
        this.userIds = new ArrayList<String>();
      }
      this.userIds.add(elem);
    }

    public List<String> getUserIds() {
      return this.userIds;
    }

    public removeUsersFromGroup_args setUserIds(List<String> userIds) {
      this.userIds = userIds;
      return this;
    }

    public void unsetUserIds() {
      this.userIds = null;
    }

    /** Returns true if field userIds is set (has been assigned a value) and false otherwise */
    public boolean isSetUserIds() {
      return this.userIds != null;
    }

    public void setUserIdsIsSet(boolean value) {
      if (!value) {
        this.userIds = null;
      }
    }

    public String getGroupId() {
      return this.groupId;
    }

    public removeUsersFromGroup_args setGroupId(String groupId) {
      this.groupId = groupId;
      return this;
    }

    public void unsetGroupId() {
      this.groupId = null;
    }

    /** Returns true if field groupId is set (has been assigned a value) and false otherwise */
    public boolean isSetGroupId() {
      return this.groupId != null;
    }

    public void setGroupIdIsSet(boolean value) {
      if (!value) {
        this.groupId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case USER_IDS:
        if (value == null) {
          unsetUserIds();
        } else {
          setUserIds((List<String>)value);
        }
        break;

      case GROUP_ID:
        if (value == null) {
          unsetGroupId();
        } else {
          setGroupId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case USER_IDS:
        return getUserIds();

      case GROUP_ID:
        return getGroupId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case USER_IDS:
        return isSetUserIds();
      case GROUP_ID:
        return isSetGroupId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof removeUsersFromGroup_args)
        return this.equals((removeUsersFromGroup_args)that);
      return false;
    }

    public boolean equals(removeUsersFromGroup_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_userIds = true && this.isSetUserIds();
      boolean that_present_userIds = true && that.isSetUserIds();
      if (this_present_userIds || that_present_userIds) {
        if (!(this_present_userIds && that_present_userIds))
          return false;
        if (!this.userIds.equals(that.userIds))
          return false;
      }

      boolean this_present_groupId = true && this.isSetGroupId();
      boolean that_present_groupId = true && that.isSetGroupId();
      if (this_present_groupId || that_present_groupId) {
        if (!(this_present_groupId && that_present_groupId))
          return false;
        if (!this.groupId.equals(that.groupId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_userIds = true && (isSetUserIds());
      list.add(present_userIds);
      if (present_userIds)
        list.add(userIds);

      boolean present_groupId = true && (isSetGroupId());
      list.add(present_groupId);
      if (present_groupId)
        list.add(groupId);

      return list.hashCode();
    }

    @Override
    public int compareTo(removeUsersFromGroup_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetUserIds()).compareTo(other.isSetUserIds());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetUserIds()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.userIds, other.userIds);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetGroupId()).compareTo(other.isSetGroupId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetGroupId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.groupId, other.groupId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("removeUsersFromGroup_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("userIds:");
      if (this.userIds == null) {
        sb.append("null");
      } else {
        sb.append(this.userIds);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("groupId:");
      if (this.groupId == null) {
        sb.append("null");
      } else {
        sb.append(this.groupId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (userIds == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'userIds' was not present! Struct: " + toString());
      }
      if (groupId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'groupId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class removeUsersFromGroup_argsStandardSchemeFactory implements SchemeFactory {
      public removeUsersFromGroup_argsStandardScheme getScheme() {
        return new removeUsersFromGroup_argsStandardScheme();
      }
    }

    private static class removeUsersFromGroup_argsStandardScheme extends StandardScheme<removeUsersFromGroup_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, removeUsersFromGroup_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // USER_IDS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list32 = iprot.readListBegin();
                  struct.userIds = new ArrayList<String>(_list32.size);
                  String _elem33;
                  for (int _i34 = 0; _i34 < _list32.size; ++_i34)
                  {
                    _elem33 = iprot.readString();
                    struct.userIds.add(_elem33);
                  }
                  iprot.readListEnd();
                }
                struct.setUserIdsIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // GROUP_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.groupId = iprot.readString();
                struct.setGroupIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, removeUsersFromGroup_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.userIds != null) {
          oprot.writeFieldBegin(USER_IDS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.userIds.size()));
            for (String _iter35 : struct.userIds)
            {
              oprot.writeString(_iter35);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.groupId != null) {
          oprot.writeFieldBegin(GROUP_ID_FIELD_DESC);
          oprot.writeString(struct.groupId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class removeUsersFromGroup_argsTupleSchemeFactory implements SchemeFactory {
      public removeUsersFromGroup_argsTupleScheme getScheme() {
        return new removeUsersFromGroup_argsTupleScheme();
      }
    }

    private static class removeUsersFromGroup_argsTupleScheme extends TupleScheme<removeUsersFromGroup_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, removeUsersFromGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        {
          oprot.writeI32(struct.userIds.size());
          for (String _iter36 : struct.userIds)
          {
            oprot.writeString(_iter36);
          }
        }
        oprot.writeString(struct.groupId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, removeUsersFromGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        {
          org.apache.thrift.protocol.TList _list37 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
          struct.userIds = new ArrayList<String>(_list37.size);
          String _elem38;
          for (int _i39 = 0; _i39 < _list37.size; ++_i39)
          {
            _elem38 = iprot.readString();
            struct.userIds.add(_elem38);
          }
        }
        struct.setUserIdsIsSet(true);
        struct.groupId = iprot.readString();
        struct.setGroupIdIsSet(true);
      }
    }

  }

  public static class removeUsersFromGroup_result implements org.apache.thrift.TBase<removeUsersFromGroup_result, removeUsersFromGroup_result._Fields>, java.io.Serializable, Cloneable, Comparable<removeUsersFromGroup_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("removeUsersFromGroup_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new removeUsersFromGroup_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new removeUsersFromGroup_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(removeUsersFromGroup_result.class, metaDataMap);
    }

    public removeUsersFromGroup_result() {
    }

    public removeUsersFromGroup_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public removeUsersFromGroup_result(removeUsersFromGroup_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public removeUsersFromGroup_result deepCopy() {
      return new removeUsersFromGroup_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public removeUsersFromGroup_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public removeUsersFromGroup_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof removeUsersFromGroup_result)
        return this.equals((removeUsersFromGroup_result)that);
      return false;
    }

    public boolean equals(removeUsersFromGroup_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(removeUsersFromGroup_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("removeUsersFromGroup_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class removeUsersFromGroup_resultStandardSchemeFactory implements SchemeFactory {
      public removeUsersFromGroup_resultStandardScheme getScheme() {
        return new removeUsersFromGroup_resultStandardScheme();
      }
    }

    private static class removeUsersFromGroup_resultStandardScheme extends StandardScheme<removeUsersFromGroup_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, removeUsersFromGroup_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, removeUsersFromGroup_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class removeUsersFromGroup_resultTupleSchemeFactory implements SchemeFactory {
      public removeUsersFromGroup_resultTupleScheme getScheme() {
        return new removeUsersFromGroup_resultTupleScheme();
      }
    }

    private static class removeUsersFromGroup_resultTupleScheme extends TupleScheme<removeUsersFromGroup_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, removeUsersFromGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, removeUsersFromGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getGroupMembersOfTypeUser_args implements org.apache.thrift.TBase<getGroupMembersOfTypeUser_args, getGroupMembersOfTypeUser_args._Fields>, java.io.Serializable, Cloneable, Comparable<getGroupMembersOfTypeUser_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getGroupMembersOfTypeUser_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField GROUP_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("groupId", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField OFFSET_FIELD_DESC = new org.apache.thrift.protocol.TField("offset", org.apache.thrift.protocol.TType.I32, (short)3);
    private static final org.apache.thrift.protocol.TField LIMIT_FIELD_DESC = new org.apache.thrift.protocol.TField("limit", org.apache.thrift.protocol.TType.I32, (short)4);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getGroupMembersOfTypeUser_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getGroupMembersOfTypeUser_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String groupId; // required
    public int offset; // required
    public int limit; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      GROUP_ID((short)2, "groupId"),
      OFFSET((short)3, "offset"),
      LIMIT((short)4, "limit");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // GROUP_ID
            return GROUP_ID;
          case 3: // OFFSET
            return OFFSET;
          case 4: // LIMIT
            return LIMIT;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __OFFSET_ISSET_ID = 0;
    private static final int __LIMIT_ISSET_ID = 1;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.GROUP_ID, new org.apache.thrift.meta_data.FieldMetaData("groupId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.OFFSET, new org.apache.thrift.meta_data.FieldMetaData("offset", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      tmpMap.put(_Fields.LIMIT, new org.apache.thrift.meta_data.FieldMetaData("limit", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getGroupMembersOfTypeUser_args.class, metaDataMap);
    }

    public getGroupMembersOfTypeUser_args() {
    }

    public getGroupMembersOfTypeUser_args(
      String domainId,
      String groupId,
      int offset,
      int limit)
    {
      this();
      this.domainId = domainId;
      this.groupId = groupId;
      this.offset = offset;
      setOffsetIsSet(true);
      this.limit = limit;
      setLimitIsSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getGroupMembersOfTypeUser_args(getGroupMembersOfTypeUser_args other) {
      __isset_bitfield = other.__isset_bitfield;
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetGroupId()) {
        this.groupId = other.groupId;
      }
      this.offset = other.offset;
      this.limit = other.limit;
    }

    public getGroupMembersOfTypeUser_args deepCopy() {
      return new getGroupMembersOfTypeUser_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.groupId = null;
      setOffsetIsSet(false);
      this.offset = 0;
      setLimitIsSet(false);
      this.limit = 0;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getGroupMembersOfTypeUser_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getGroupId() {
      return this.groupId;
    }

    public getGroupMembersOfTypeUser_args setGroupId(String groupId) {
      this.groupId = groupId;
      return this;
    }

    public void unsetGroupId() {
      this.groupId = null;
    }

    /** Returns true if field groupId is set (has been assigned a value) and false otherwise */
    public boolean isSetGroupId() {
      return this.groupId != null;
    }

    public void setGroupIdIsSet(boolean value) {
      if (!value) {
        this.groupId = null;
      }
    }

    public int getOffset() {
      return this.offset;
    }

    public getGroupMembersOfTypeUser_args setOffset(int offset) {
      this.offset = offset;
      setOffsetIsSet(true);
      return this;
    }

    public void unsetOffset() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    /** Returns true if field offset is set (has been assigned a value) and false otherwise */
    public boolean isSetOffset() {
      return EncodingUtils.testBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    public void setOffsetIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __OFFSET_ISSET_ID, value);
    }

    public int getLimit() {
      return this.limit;
    }

    public getGroupMembersOfTypeUser_args setLimit(int limit) {
      this.limit = limit;
      setLimitIsSet(true);
      return this;
    }

    public void unsetLimit() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    /** Returns true if field limit is set (has been assigned a value) and false otherwise */
    public boolean isSetLimit() {
      return EncodingUtils.testBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    public void setLimitIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __LIMIT_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case GROUP_ID:
        if (value == null) {
          unsetGroupId();
        } else {
          setGroupId((String)value);
        }
        break;

      case OFFSET:
        if (value == null) {
          unsetOffset();
        } else {
          setOffset((Integer)value);
        }
        break;

      case LIMIT:
        if (value == null) {
          unsetLimit();
        } else {
          setLimit((Integer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case GROUP_ID:
        return getGroupId();

      case OFFSET:
        return getOffset();

      case LIMIT:
        return getLimit();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case GROUP_ID:
        return isSetGroupId();
      case OFFSET:
        return isSetOffset();
      case LIMIT:
        return isSetLimit();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getGroupMembersOfTypeUser_args)
        return this.equals((getGroupMembersOfTypeUser_args)that);
      return false;
    }

    public boolean equals(getGroupMembersOfTypeUser_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_groupId = true && this.isSetGroupId();
      boolean that_present_groupId = true && that.isSetGroupId();
      if (this_present_groupId || that_present_groupId) {
        if (!(this_present_groupId && that_present_groupId))
          return false;
        if (!this.groupId.equals(that.groupId))
          return false;
      }

      boolean this_present_offset = true;
      boolean that_present_offset = true;
      if (this_present_offset || that_present_offset) {
        if (!(this_present_offset && that_present_offset))
          return false;
        if (this.offset != that.offset)
          return false;
      }

      boolean this_present_limit = true;
      boolean that_present_limit = true;
      if (this_present_limit || that_present_limit) {
        if (!(this_present_limit && that_present_limit))
          return false;
        if (this.limit != that.limit)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_groupId = true && (isSetGroupId());
      list.add(present_groupId);
      if (present_groupId)
        list.add(groupId);

      boolean present_offset = true;
      list.add(present_offset);
      if (present_offset)
        list.add(offset);

      boolean present_limit = true;
      list.add(present_limit);
      if (present_limit)
        list.add(limit);

      return list.hashCode();
    }

    @Override
    public int compareTo(getGroupMembersOfTypeUser_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetGroupId()).compareTo(other.isSetGroupId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetGroupId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.groupId, other.groupId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetOffset()).compareTo(other.isSetOffset());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetOffset()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.offset, other.offset);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetLimit()).compareTo(other.isSetLimit());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetLimit()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.limit, other.limit);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getGroupMembersOfTypeUser_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("groupId:");
      if (this.groupId == null) {
        sb.append("null");
      } else {
        sb.append(this.groupId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("offset:");
      sb.append(this.offset);
      first = false;
      if (!first) sb.append(", ");
      sb.append("limit:");
      sb.append(this.limit);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (groupId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'groupId' was not present! Struct: " + toString());
      }
      // alas, we cannot check 'offset' because it's a primitive and you chose the non-beans generator.
      // alas, we cannot check 'limit' because it's a primitive and you chose the non-beans generator.
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getGroupMembersOfTypeUser_argsStandardSchemeFactory implements SchemeFactory {
      public getGroupMembersOfTypeUser_argsStandardScheme getScheme() {
        return new getGroupMembersOfTypeUser_argsStandardScheme();
      }
    }

    private static class getGroupMembersOfTypeUser_argsStandardScheme extends StandardScheme<getGroupMembersOfTypeUser_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getGroupMembersOfTypeUser_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // GROUP_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.groupId = iprot.readString();
                struct.setGroupIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // OFFSET
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.offset = iprot.readI32();
                struct.setOffsetIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 4: // LIMIT
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.limit = iprot.readI32();
                struct.setLimitIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        if (!struct.isSetOffset()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'offset' was not found in serialized data! Struct: " + toString());
        }
        if (!struct.isSetLimit()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'limit' was not found in serialized data! Struct: " + toString());
        }
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getGroupMembersOfTypeUser_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.groupId != null) {
          oprot.writeFieldBegin(GROUP_ID_FIELD_DESC);
          oprot.writeString(struct.groupId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldBegin(OFFSET_FIELD_DESC);
        oprot.writeI32(struct.offset);
        oprot.writeFieldEnd();
        oprot.writeFieldBegin(LIMIT_FIELD_DESC);
        oprot.writeI32(struct.limit);
        oprot.writeFieldEnd();
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getGroupMembersOfTypeUser_argsTupleSchemeFactory implements SchemeFactory {
      public getGroupMembersOfTypeUser_argsTupleScheme getScheme() {
        return new getGroupMembersOfTypeUser_argsTupleScheme();
      }
    }

    private static class getGroupMembersOfTypeUser_argsTupleScheme extends TupleScheme<getGroupMembersOfTypeUser_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getGroupMembersOfTypeUser_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.groupId);
        oprot.writeI32(struct.offset);
        oprot.writeI32(struct.limit);
        BitSet optionals = new BitSet();
        if (struct.isSetDomainId()) {
          optionals.set(0);
        }
        oprot.writeBitSet(optionals, 1);
        if (struct.isSetDomainId()) {
          oprot.writeString(struct.domainId);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getGroupMembersOfTypeUser_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.groupId = iprot.readString();
        struct.setGroupIdIsSet(true);
        struct.offset = iprot.readI32();
        struct.setOffsetIsSet(true);
        struct.limit = iprot.readI32();
        struct.setLimitIsSet(true);
        BitSet incoming = iprot.readBitSet(1);
        if (incoming.get(0)) {
          struct.domainId = iprot.readString();
          struct.setDomainIdIsSet(true);
        }
      }
    }

  }

  public static class getGroupMembersOfTypeUser_result implements org.apache.thrift.TBase<getGroupMembersOfTypeUser_result, getGroupMembersOfTypeUser_result._Fields>, java.io.Serializable, Cloneable, Comparable<getGroupMembersOfTypeUser_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getGroupMembersOfTypeUser_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getGroupMembersOfTypeUser_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getGroupMembersOfTypeUser_resultTupleSchemeFactory());
    }

    public List<org.apache.airavata.sharing.registry.models.User> success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.User.class))));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getGroupMembersOfTypeUser_result.class, metaDataMap);
    }

    public getGroupMembersOfTypeUser_result() {
    }

    public getGroupMembersOfTypeUser_result(
      List<org.apache.airavata.sharing.registry.models.User> success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getGroupMembersOfTypeUser_result(getGroupMembersOfTypeUser_result other) {
      if (other.isSetSuccess()) {
        List<org.apache.airavata.sharing.registry.models.User> __this__success = new ArrayList<org.apache.airavata.sharing.registry.models.User>(other.success.size());
        for (org.apache.airavata.sharing.registry.models.User other_element : other.success) {
          __this__success.add(new org.apache.airavata.sharing.registry.models.User(other_element));
        }
        this.success = __this__success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getGroupMembersOfTypeUser_result deepCopy() {
      return new getGroupMembersOfTypeUser_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public int getSuccessSize() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<org.apache.airavata.sharing.registry.models.User> getSuccessIterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void addToSuccess(org.apache.airavata.sharing.registry.models.User elem) {
      if (this.success == null) {
        this.success = new ArrayList<org.apache.airavata.sharing.registry.models.User>();
      }
      this.success.add(elem);
    }

    public List<org.apache.airavata.sharing.registry.models.User> getSuccess() {
      return this.success;
    }

    public getGroupMembersOfTypeUser_result setSuccess(List<org.apache.airavata.sharing.registry.models.User> success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getGroupMembersOfTypeUser_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((List<org.apache.airavata.sharing.registry.models.User>)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getGroupMembersOfTypeUser_result)
        return this.equals((getGroupMembersOfTypeUser_result)that);
      return false;
    }

    public boolean equals(getGroupMembersOfTypeUser_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getGroupMembersOfTypeUser_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getGroupMembersOfTypeUser_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getGroupMembersOfTypeUser_resultStandardSchemeFactory implements SchemeFactory {
      public getGroupMembersOfTypeUser_resultStandardScheme getScheme() {
        return new getGroupMembersOfTypeUser_resultStandardScheme();
      }
    }

    private static class getGroupMembersOfTypeUser_resultStandardScheme extends StandardScheme<getGroupMembersOfTypeUser_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getGroupMembersOfTypeUser_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list40 = iprot.readListBegin();
                  struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.User>(_list40.size);
                  org.apache.airavata.sharing.registry.models.User _elem41;
                  for (int _i42 = 0; _i42 < _list40.size; ++_i42)
                  {
                    _elem41 = new org.apache.airavata.sharing.registry.models.User();
                    _elem41.read(iprot);
                    struct.success.add(_elem41);
                  }
                  iprot.readListEnd();
                }
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getGroupMembersOfTypeUser_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (org.apache.airavata.sharing.registry.models.User _iter43 : struct.success)
            {
              _iter43.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getGroupMembersOfTypeUser_resultTupleSchemeFactory implements SchemeFactory {
      public getGroupMembersOfTypeUser_resultTupleScheme getScheme() {
        return new getGroupMembersOfTypeUser_resultTupleScheme();
      }
    }

    private static class getGroupMembersOfTypeUser_resultTupleScheme extends TupleScheme<getGroupMembersOfTypeUser_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getGroupMembersOfTypeUser_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          {
            oprot.writeI32(struct.success.size());
            for (org.apache.airavata.sharing.registry.models.User _iter44 : struct.success)
            {
              _iter44.write(oprot);
            }
          }
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getGroupMembersOfTypeUser_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list45 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.User>(_list45.size);
            org.apache.airavata.sharing.registry.models.User _elem46;
            for (int _i47 = 0; _i47 < _list45.size; ++_i47)
            {
              _elem46 = new org.apache.airavata.sharing.registry.models.User();
              _elem46.read(iprot);
              struct.success.add(_elem46);
            }
          }
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getGroupMembersOfTypeGroup_args implements org.apache.thrift.TBase<getGroupMembersOfTypeGroup_args, getGroupMembersOfTypeGroup_args._Fields>, java.io.Serializable, Cloneable, Comparable<getGroupMembersOfTypeGroup_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getGroupMembersOfTypeGroup_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField GROUP_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("groupId", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField OFFSET_FIELD_DESC = new org.apache.thrift.protocol.TField("offset", org.apache.thrift.protocol.TType.I32, (short)3);
    private static final org.apache.thrift.protocol.TField LIMIT_FIELD_DESC = new org.apache.thrift.protocol.TField("limit", org.apache.thrift.protocol.TType.I32, (short)4);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getGroupMembersOfTypeGroup_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getGroupMembersOfTypeGroup_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String groupId; // required
    public int offset; // required
    public int limit; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      GROUP_ID((short)2, "groupId"),
      OFFSET((short)3, "offset"),
      LIMIT((short)4, "limit");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // GROUP_ID
            return GROUP_ID;
          case 3: // OFFSET
            return OFFSET;
          case 4: // LIMIT
            return LIMIT;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __OFFSET_ISSET_ID = 0;
    private static final int __LIMIT_ISSET_ID = 1;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.GROUP_ID, new org.apache.thrift.meta_data.FieldMetaData("groupId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.OFFSET, new org.apache.thrift.meta_data.FieldMetaData("offset", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      tmpMap.put(_Fields.LIMIT, new org.apache.thrift.meta_data.FieldMetaData("limit", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getGroupMembersOfTypeGroup_args.class, metaDataMap);
    }

    public getGroupMembersOfTypeGroup_args() {
    }

    public getGroupMembersOfTypeGroup_args(
      String domainId,
      String groupId,
      int offset,
      int limit)
    {
      this();
      this.domainId = domainId;
      this.groupId = groupId;
      this.offset = offset;
      setOffsetIsSet(true);
      this.limit = limit;
      setLimitIsSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getGroupMembersOfTypeGroup_args(getGroupMembersOfTypeGroup_args other) {
      __isset_bitfield = other.__isset_bitfield;
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetGroupId()) {
        this.groupId = other.groupId;
      }
      this.offset = other.offset;
      this.limit = other.limit;
    }

    public getGroupMembersOfTypeGroup_args deepCopy() {
      return new getGroupMembersOfTypeGroup_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.groupId = null;
      setOffsetIsSet(false);
      this.offset = 0;
      setLimitIsSet(false);
      this.limit = 0;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getGroupMembersOfTypeGroup_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getGroupId() {
      return this.groupId;
    }

    public getGroupMembersOfTypeGroup_args setGroupId(String groupId) {
      this.groupId = groupId;
      return this;
    }

    public void unsetGroupId() {
      this.groupId = null;
    }

    /** Returns true if field groupId is set (has been assigned a value) and false otherwise */
    public boolean isSetGroupId() {
      return this.groupId != null;
    }

    public void setGroupIdIsSet(boolean value) {
      if (!value) {
        this.groupId = null;
      }
    }

    public int getOffset() {
      return this.offset;
    }

    public getGroupMembersOfTypeGroup_args setOffset(int offset) {
      this.offset = offset;
      setOffsetIsSet(true);
      return this;
    }

    public void unsetOffset() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    /** Returns true if field offset is set (has been assigned a value) and false otherwise */
    public boolean isSetOffset() {
      return EncodingUtils.testBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    public void setOffsetIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __OFFSET_ISSET_ID, value);
    }

    public int getLimit() {
      return this.limit;
    }

    public getGroupMembersOfTypeGroup_args setLimit(int limit) {
      this.limit = limit;
      setLimitIsSet(true);
      return this;
    }

    public void unsetLimit() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    /** Returns true if field limit is set (has been assigned a value) and false otherwise */
    public boolean isSetLimit() {
      return EncodingUtils.testBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    public void setLimitIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __LIMIT_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case GROUP_ID:
        if (value == null) {
          unsetGroupId();
        } else {
          setGroupId((String)value);
        }
        break;

      case OFFSET:
        if (value == null) {
          unsetOffset();
        } else {
          setOffset((Integer)value);
        }
        break;

      case LIMIT:
        if (value == null) {
          unsetLimit();
        } else {
          setLimit((Integer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case GROUP_ID:
        return getGroupId();

      case OFFSET:
        return getOffset();

      case LIMIT:
        return getLimit();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case GROUP_ID:
        return isSetGroupId();
      case OFFSET:
        return isSetOffset();
      case LIMIT:
        return isSetLimit();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getGroupMembersOfTypeGroup_args)
        return this.equals((getGroupMembersOfTypeGroup_args)that);
      return false;
    }

    public boolean equals(getGroupMembersOfTypeGroup_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_groupId = true && this.isSetGroupId();
      boolean that_present_groupId = true && that.isSetGroupId();
      if (this_present_groupId || that_present_groupId) {
        if (!(this_present_groupId && that_present_groupId))
          return false;
        if (!this.groupId.equals(that.groupId))
          return false;
      }

      boolean this_present_offset = true;
      boolean that_present_offset = true;
      if (this_present_offset || that_present_offset) {
        if (!(this_present_offset && that_present_offset))
          return false;
        if (this.offset != that.offset)
          return false;
      }

      boolean this_present_limit = true;
      boolean that_present_limit = true;
      if (this_present_limit || that_present_limit) {
        if (!(this_present_limit && that_present_limit))
          return false;
        if (this.limit != that.limit)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_groupId = true && (isSetGroupId());
      list.add(present_groupId);
      if (present_groupId)
        list.add(groupId);

      boolean present_offset = true;
      list.add(present_offset);
      if (present_offset)
        list.add(offset);

      boolean present_limit = true;
      list.add(present_limit);
      if (present_limit)
        list.add(limit);

      return list.hashCode();
    }

    @Override
    public int compareTo(getGroupMembersOfTypeGroup_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetGroupId()).compareTo(other.isSetGroupId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetGroupId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.groupId, other.groupId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetOffset()).compareTo(other.isSetOffset());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetOffset()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.offset, other.offset);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetLimit()).compareTo(other.isSetLimit());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetLimit()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.limit, other.limit);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getGroupMembersOfTypeGroup_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("groupId:");
      if (this.groupId == null) {
        sb.append("null");
      } else {
        sb.append(this.groupId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("offset:");
      sb.append(this.offset);
      first = false;
      if (!first) sb.append(", ");
      sb.append("limit:");
      sb.append(this.limit);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (groupId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'groupId' was not present! Struct: " + toString());
      }
      // alas, we cannot check 'offset' because it's a primitive and you chose the non-beans generator.
      // alas, we cannot check 'limit' because it's a primitive and you chose the non-beans generator.
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getGroupMembersOfTypeGroup_argsStandardSchemeFactory implements SchemeFactory {
      public getGroupMembersOfTypeGroup_argsStandardScheme getScheme() {
        return new getGroupMembersOfTypeGroup_argsStandardScheme();
      }
    }

    private static class getGroupMembersOfTypeGroup_argsStandardScheme extends StandardScheme<getGroupMembersOfTypeGroup_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getGroupMembersOfTypeGroup_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // GROUP_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.groupId = iprot.readString();
                struct.setGroupIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // OFFSET
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.offset = iprot.readI32();
                struct.setOffsetIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 4: // LIMIT
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.limit = iprot.readI32();
                struct.setLimitIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        if (!struct.isSetOffset()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'offset' was not found in serialized data! Struct: " + toString());
        }
        if (!struct.isSetLimit()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'limit' was not found in serialized data! Struct: " + toString());
        }
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getGroupMembersOfTypeGroup_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.groupId != null) {
          oprot.writeFieldBegin(GROUP_ID_FIELD_DESC);
          oprot.writeString(struct.groupId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldBegin(OFFSET_FIELD_DESC);
        oprot.writeI32(struct.offset);
        oprot.writeFieldEnd();
        oprot.writeFieldBegin(LIMIT_FIELD_DESC);
        oprot.writeI32(struct.limit);
        oprot.writeFieldEnd();
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getGroupMembersOfTypeGroup_argsTupleSchemeFactory implements SchemeFactory {
      public getGroupMembersOfTypeGroup_argsTupleScheme getScheme() {
        return new getGroupMembersOfTypeGroup_argsTupleScheme();
      }
    }

    private static class getGroupMembersOfTypeGroup_argsTupleScheme extends TupleScheme<getGroupMembersOfTypeGroup_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getGroupMembersOfTypeGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.groupId);
        oprot.writeI32(struct.offset);
        oprot.writeI32(struct.limit);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getGroupMembersOfTypeGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.groupId = iprot.readString();
        struct.setGroupIdIsSet(true);
        struct.offset = iprot.readI32();
        struct.setOffsetIsSet(true);
        struct.limit = iprot.readI32();
        struct.setLimitIsSet(true);
      }
    }

  }

  public static class getGroupMembersOfTypeGroup_result implements org.apache.thrift.TBase<getGroupMembersOfTypeGroup_result, getGroupMembersOfTypeGroup_result._Fields>, java.io.Serializable, Cloneable, Comparable<getGroupMembersOfTypeGroup_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getGroupMembersOfTypeGroup_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getGroupMembersOfTypeGroup_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getGroupMembersOfTypeGroup_resultTupleSchemeFactory());
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.UserGroup.class))));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getGroupMembersOfTypeGroup_result.class, metaDataMap);
    }

    public getGroupMembersOfTypeGroup_result() {
    }

    public getGroupMembersOfTypeGroup_result(
      List<org.apache.airavata.sharing.registry.models.UserGroup> success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getGroupMembersOfTypeGroup_result(getGroupMembersOfTypeGroup_result other) {
      if (other.isSetSuccess()) {
        List<org.apache.airavata.sharing.registry.models.UserGroup> __this__success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>(other.success.size());
        for (org.apache.airavata.sharing.registry.models.UserGroup other_element : other.success) {
          __this__success.add(new org.apache.airavata.sharing.registry.models.UserGroup(other_element));
        }
        this.success = __this__success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getGroupMembersOfTypeGroup_result deepCopy() {
      return new getGroupMembersOfTypeGroup_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public int getSuccessSize() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<org.apache.airavata.sharing.registry.models.UserGroup> getSuccessIterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void addToSuccess(org.apache.airavata.sharing.registry.models.UserGroup elem) {
      if (this.success == null) {
        this.success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>();
      }
      this.success.add(elem);
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> getSuccess() {
      return this.success;
    }

    public getGroupMembersOfTypeGroup_result setSuccess(List<org.apache.airavata.sharing.registry.models.UserGroup> success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getGroupMembersOfTypeGroup_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((List<org.apache.airavata.sharing.registry.models.UserGroup>)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getGroupMembersOfTypeGroup_result)
        return this.equals((getGroupMembersOfTypeGroup_result)that);
      return false;
    }

    public boolean equals(getGroupMembersOfTypeGroup_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getGroupMembersOfTypeGroup_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getGroupMembersOfTypeGroup_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getGroupMembersOfTypeGroup_resultStandardSchemeFactory implements SchemeFactory {
      public getGroupMembersOfTypeGroup_resultStandardScheme getScheme() {
        return new getGroupMembersOfTypeGroup_resultStandardScheme();
      }
    }

    private static class getGroupMembersOfTypeGroup_resultStandardScheme extends StandardScheme<getGroupMembersOfTypeGroup_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getGroupMembersOfTypeGroup_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list48 = iprot.readListBegin();
                  struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>(_list48.size);
                  org.apache.airavata.sharing.registry.models.UserGroup _elem49;
                  for (int _i50 = 0; _i50 < _list48.size; ++_i50)
                  {
                    _elem49 = new org.apache.airavata.sharing.registry.models.UserGroup();
                    _elem49.read(iprot);
                    struct.success.add(_elem49);
                  }
                  iprot.readListEnd();
                }
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getGroupMembersOfTypeGroup_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (org.apache.airavata.sharing.registry.models.UserGroup _iter51 : struct.success)
            {
              _iter51.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getGroupMembersOfTypeGroup_resultTupleSchemeFactory implements SchemeFactory {
      public getGroupMembersOfTypeGroup_resultTupleScheme getScheme() {
        return new getGroupMembersOfTypeGroup_resultTupleScheme();
      }
    }

    private static class getGroupMembersOfTypeGroup_resultTupleScheme extends TupleScheme<getGroupMembersOfTypeGroup_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getGroupMembersOfTypeGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          {
            oprot.writeI32(struct.success.size());
            for (org.apache.airavata.sharing.registry.models.UserGroup _iter52 : struct.success)
            {
              _iter52.write(oprot);
            }
          }
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getGroupMembersOfTypeGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list53 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>(_list53.size);
            org.apache.airavata.sharing.registry.models.UserGroup _elem54;
            for (int _i55 = 0; _i55 < _list53.size; ++_i55)
            {
              _elem54 = new org.apache.airavata.sharing.registry.models.UserGroup();
              _elem54.read(iprot);
              struct.success.add(_elem54);
            }
          }
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class addChildGroupsToParentGroup_args implements org.apache.thrift.TBase<addChildGroupsToParentGroup_args, addChildGroupsToParentGroup_args._Fields>, java.io.Serializable, Cloneable, Comparable<addChildGroupsToParentGroup_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("addChildGroupsToParentGroup_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField CHILD_IDS_FIELD_DESC = new org.apache.thrift.protocol.TField("childIds", org.apache.thrift.protocol.TType.LIST, (short)2);
    private static final org.apache.thrift.protocol.TField GROUP_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("groupId", org.apache.thrift.protocol.TType.STRING, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new addChildGroupsToParentGroup_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new addChildGroupsToParentGroup_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public List<String> childIds; // required
    public String groupId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      CHILD_IDS((short)2, "childIds"),
      GROUP_ID((short)3, "groupId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // CHILD_IDS
            return CHILD_IDS;
          case 3: // GROUP_ID
            return GROUP_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.CHILD_IDS, new org.apache.thrift.meta_data.FieldMetaData("childIds", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
      tmpMap.put(_Fields.GROUP_ID, new org.apache.thrift.meta_data.FieldMetaData("groupId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(addChildGroupsToParentGroup_args.class, metaDataMap);
    }

    public addChildGroupsToParentGroup_args() {
    }

    public addChildGroupsToParentGroup_args(
      String domainId,
      List<String> childIds,
      String groupId)
    {
      this();
      this.domainId = domainId;
      this.childIds = childIds;
      this.groupId = groupId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public addChildGroupsToParentGroup_args(addChildGroupsToParentGroup_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetChildIds()) {
        List<String> __this__childIds = new ArrayList<String>(other.childIds);
        this.childIds = __this__childIds;
      }
      if (other.isSetGroupId()) {
        this.groupId = other.groupId;
      }
    }

    public addChildGroupsToParentGroup_args deepCopy() {
      return new addChildGroupsToParentGroup_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.childIds = null;
      this.groupId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public addChildGroupsToParentGroup_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public int getChildIdsSize() {
      return (this.childIds == null) ? 0 : this.childIds.size();
    }

    public java.util.Iterator<String> getChildIdsIterator() {
      return (this.childIds == null) ? null : this.childIds.iterator();
    }

    public void addToChildIds(String elem) {
      if (this.childIds == null) {
        this.childIds = new ArrayList<String>();
      }
      this.childIds.add(elem);
    }

    public List<String> getChildIds() {
      return this.childIds;
    }

    public addChildGroupsToParentGroup_args setChildIds(List<String> childIds) {
      this.childIds = childIds;
      return this;
    }

    public void unsetChildIds() {
      this.childIds = null;
    }

    /** Returns true if field childIds is set (has been assigned a value) and false otherwise */
    public boolean isSetChildIds() {
      return this.childIds != null;
    }

    public void setChildIdsIsSet(boolean value) {
      if (!value) {
        this.childIds = null;
      }
    }

    public String getGroupId() {
      return this.groupId;
    }

    public addChildGroupsToParentGroup_args setGroupId(String groupId) {
      this.groupId = groupId;
      return this;
    }

    public void unsetGroupId() {
      this.groupId = null;
    }

    /** Returns true if field groupId is set (has been assigned a value) and false otherwise */
    public boolean isSetGroupId() {
      return this.groupId != null;
    }

    public void setGroupIdIsSet(boolean value) {
      if (!value) {
        this.groupId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case CHILD_IDS:
        if (value == null) {
          unsetChildIds();
        } else {
          setChildIds((List<String>)value);
        }
        break;

      case GROUP_ID:
        if (value == null) {
          unsetGroupId();
        } else {
          setGroupId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case CHILD_IDS:
        return getChildIds();

      case GROUP_ID:
        return getGroupId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case CHILD_IDS:
        return isSetChildIds();
      case GROUP_ID:
        return isSetGroupId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof addChildGroupsToParentGroup_args)
        return this.equals((addChildGroupsToParentGroup_args)that);
      return false;
    }

    public boolean equals(addChildGroupsToParentGroup_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_childIds = true && this.isSetChildIds();
      boolean that_present_childIds = true && that.isSetChildIds();
      if (this_present_childIds || that_present_childIds) {
        if (!(this_present_childIds && that_present_childIds))
          return false;
        if (!this.childIds.equals(that.childIds))
          return false;
      }

      boolean this_present_groupId = true && this.isSetGroupId();
      boolean that_present_groupId = true && that.isSetGroupId();
      if (this_present_groupId || that_present_groupId) {
        if (!(this_present_groupId && that_present_groupId))
          return false;
        if (!this.groupId.equals(that.groupId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_childIds = true && (isSetChildIds());
      list.add(present_childIds);
      if (present_childIds)
        list.add(childIds);

      boolean present_groupId = true && (isSetGroupId());
      list.add(present_groupId);
      if (present_groupId)
        list.add(groupId);

      return list.hashCode();
    }

    @Override
    public int compareTo(addChildGroupsToParentGroup_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetChildIds()).compareTo(other.isSetChildIds());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetChildIds()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.childIds, other.childIds);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetGroupId()).compareTo(other.isSetGroupId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetGroupId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.groupId, other.groupId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("addChildGroupsToParentGroup_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("childIds:");
      if (this.childIds == null) {
        sb.append("null");
      } else {
        sb.append(this.childIds);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("groupId:");
      if (this.groupId == null) {
        sb.append("null");
      } else {
        sb.append(this.groupId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (childIds == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'childIds' was not present! Struct: " + toString());
      }
      if (groupId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'groupId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class addChildGroupsToParentGroup_argsStandardSchemeFactory implements SchemeFactory {
      public addChildGroupsToParentGroup_argsStandardScheme getScheme() {
        return new addChildGroupsToParentGroup_argsStandardScheme();
      }
    }

    private static class addChildGroupsToParentGroup_argsStandardScheme extends StandardScheme<addChildGroupsToParentGroup_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, addChildGroupsToParentGroup_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // CHILD_IDS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list56 = iprot.readListBegin();
                  struct.childIds = new ArrayList<String>(_list56.size);
                  String _elem57;
                  for (int _i58 = 0; _i58 < _list56.size; ++_i58)
                  {
                    _elem57 = iprot.readString();
                    struct.childIds.add(_elem57);
                  }
                  iprot.readListEnd();
                }
                struct.setChildIdsIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // GROUP_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.groupId = iprot.readString();
                struct.setGroupIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, addChildGroupsToParentGroup_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.childIds != null) {
          oprot.writeFieldBegin(CHILD_IDS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.childIds.size()));
            for (String _iter59 : struct.childIds)
            {
              oprot.writeString(_iter59);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.groupId != null) {
          oprot.writeFieldBegin(GROUP_ID_FIELD_DESC);
          oprot.writeString(struct.groupId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class addChildGroupsToParentGroup_argsTupleSchemeFactory implements SchemeFactory {
      public addChildGroupsToParentGroup_argsTupleScheme getScheme() {
        return new addChildGroupsToParentGroup_argsTupleScheme();
      }
    }

    private static class addChildGroupsToParentGroup_argsTupleScheme extends TupleScheme<addChildGroupsToParentGroup_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, addChildGroupsToParentGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        {
          oprot.writeI32(struct.childIds.size());
          for (String _iter60 : struct.childIds)
          {
            oprot.writeString(_iter60);
          }
        }
        oprot.writeString(struct.groupId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, addChildGroupsToParentGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        {
          org.apache.thrift.protocol.TList _list61 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
          struct.childIds = new ArrayList<String>(_list61.size);
          String _elem62;
          for (int _i63 = 0; _i63 < _list61.size; ++_i63)
          {
            _elem62 = iprot.readString();
            struct.childIds.add(_elem62);
          }
        }
        struct.setChildIdsIsSet(true);
        struct.groupId = iprot.readString();
        struct.setGroupIdIsSet(true);
      }
    }

  }

  public static class addChildGroupsToParentGroup_result implements org.apache.thrift.TBase<addChildGroupsToParentGroup_result, addChildGroupsToParentGroup_result._Fields>, java.io.Serializable, Cloneable, Comparable<addChildGroupsToParentGroup_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("addChildGroupsToParentGroup_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new addChildGroupsToParentGroup_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new addChildGroupsToParentGroup_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(addChildGroupsToParentGroup_result.class, metaDataMap);
    }

    public addChildGroupsToParentGroup_result() {
    }

    public addChildGroupsToParentGroup_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public addChildGroupsToParentGroup_result(addChildGroupsToParentGroup_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public addChildGroupsToParentGroup_result deepCopy() {
      return new addChildGroupsToParentGroup_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public addChildGroupsToParentGroup_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public addChildGroupsToParentGroup_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof addChildGroupsToParentGroup_result)
        return this.equals((addChildGroupsToParentGroup_result)that);
      return false;
    }

    public boolean equals(addChildGroupsToParentGroup_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(addChildGroupsToParentGroup_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("addChildGroupsToParentGroup_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class addChildGroupsToParentGroup_resultStandardSchemeFactory implements SchemeFactory {
      public addChildGroupsToParentGroup_resultStandardScheme getScheme() {
        return new addChildGroupsToParentGroup_resultStandardScheme();
      }
    }

    private static class addChildGroupsToParentGroup_resultStandardScheme extends StandardScheme<addChildGroupsToParentGroup_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, addChildGroupsToParentGroup_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, addChildGroupsToParentGroup_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class addChildGroupsToParentGroup_resultTupleSchemeFactory implements SchemeFactory {
      public addChildGroupsToParentGroup_resultTupleScheme getScheme() {
        return new addChildGroupsToParentGroup_resultTupleScheme();
      }
    }

    private static class addChildGroupsToParentGroup_resultTupleScheme extends TupleScheme<addChildGroupsToParentGroup_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, addChildGroupsToParentGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, addChildGroupsToParentGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class removeChildGroupFromParentGroup_args implements org.apache.thrift.TBase<removeChildGroupFromParentGroup_args, removeChildGroupFromParentGroup_args._Fields>, java.io.Serializable, Cloneable, Comparable<removeChildGroupFromParentGroup_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("removeChildGroupFromParentGroup_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField CHILD_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("childId", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField GROUP_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("groupId", org.apache.thrift.protocol.TType.STRING, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new removeChildGroupFromParentGroup_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new removeChildGroupFromParentGroup_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String childId; // required
    public String groupId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      CHILD_ID((short)2, "childId"),
      GROUP_ID((short)3, "groupId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // CHILD_ID
            return CHILD_ID;
          case 3: // GROUP_ID
            return GROUP_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.CHILD_ID, new org.apache.thrift.meta_data.FieldMetaData("childId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.GROUP_ID, new org.apache.thrift.meta_data.FieldMetaData("groupId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(removeChildGroupFromParentGroup_args.class, metaDataMap);
    }

    public removeChildGroupFromParentGroup_args() {
    }

    public removeChildGroupFromParentGroup_args(
      String domainId,
      String childId,
      String groupId)
    {
      this();
      this.domainId = domainId;
      this.childId = childId;
      this.groupId = groupId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public removeChildGroupFromParentGroup_args(removeChildGroupFromParentGroup_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetChildId()) {
        this.childId = other.childId;
      }
      if (other.isSetGroupId()) {
        this.groupId = other.groupId;
      }
    }

    public removeChildGroupFromParentGroup_args deepCopy() {
      return new removeChildGroupFromParentGroup_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.childId = null;
      this.groupId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public removeChildGroupFromParentGroup_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getChildId() {
      return this.childId;
    }

    public removeChildGroupFromParentGroup_args setChildId(String childId) {
      this.childId = childId;
      return this;
    }

    public void unsetChildId() {
      this.childId = null;
    }

    /** Returns true if field childId is set (has been assigned a value) and false otherwise */
    public boolean isSetChildId() {
      return this.childId != null;
    }

    public void setChildIdIsSet(boolean value) {
      if (!value) {
        this.childId = null;
      }
    }

    public String getGroupId() {
      return this.groupId;
    }

    public removeChildGroupFromParentGroup_args setGroupId(String groupId) {
      this.groupId = groupId;
      return this;
    }

    public void unsetGroupId() {
      this.groupId = null;
    }

    /** Returns true if field groupId is set (has been assigned a value) and false otherwise */
    public boolean isSetGroupId() {
      return this.groupId != null;
    }

    public void setGroupIdIsSet(boolean value) {
      if (!value) {
        this.groupId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case CHILD_ID:
        if (value == null) {
          unsetChildId();
        } else {
          setChildId((String)value);
        }
        break;

      case GROUP_ID:
        if (value == null) {
          unsetGroupId();
        } else {
          setGroupId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case CHILD_ID:
        return getChildId();

      case GROUP_ID:
        return getGroupId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case CHILD_ID:
        return isSetChildId();
      case GROUP_ID:
        return isSetGroupId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof removeChildGroupFromParentGroup_args)
        return this.equals((removeChildGroupFromParentGroup_args)that);
      return false;
    }

    public boolean equals(removeChildGroupFromParentGroup_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_childId = true && this.isSetChildId();
      boolean that_present_childId = true && that.isSetChildId();
      if (this_present_childId || that_present_childId) {
        if (!(this_present_childId && that_present_childId))
          return false;
        if (!this.childId.equals(that.childId))
          return false;
      }

      boolean this_present_groupId = true && this.isSetGroupId();
      boolean that_present_groupId = true && that.isSetGroupId();
      if (this_present_groupId || that_present_groupId) {
        if (!(this_present_groupId && that_present_groupId))
          return false;
        if (!this.groupId.equals(that.groupId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_childId = true && (isSetChildId());
      list.add(present_childId);
      if (present_childId)
        list.add(childId);

      boolean present_groupId = true && (isSetGroupId());
      list.add(present_groupId);
      if (present_groupId)
        list.add(groupId);

      return list.hashCode();
    }

    @Override
    public int compareTo(removeChildGroupFromParentGroup_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetChildId()).compareTo(other.isSetChildId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetChildId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.childId, other.childId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetGroupId()).compareTo(other.isSetGroupId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetGroupId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.groupId, other.groupId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("removeChildGroupFromParentGroup_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("childId:");
      if (this.childId == null) {
        sb.append("null");
      } else {
        sb.append(this.childId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("groupId:");
      if (this.groupId == null) {
        sb.append("null");
      } else {
        sb.append(this.groupId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (childId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'childId' was not present! Struct: " + toString());
      }
      if (groupId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'groupId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class removeChildGroupFromParentGroup_argsStandardSchemeFactory implements SchemeFactory {
      public removeChildGroupFromParentGroup_argsStandardScheme getScheme() {
        return new removeChildGroupFromParentGroup_argsStandardScheme();
      }
    }

    private static class removeChildGroupFromParentGroup_argsStandardScheme extends StandardScheme<removeChildGroupFromParentGroup_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, removeChildGroupFromParentGroup_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // CHILD_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.childId = iprot.readString();
                struct.setChildIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // GROUP_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.groupId = iprot.readString();
                struct.setGroupIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, removeChildGroupFromParentGroup_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.childId != null) {
          oprot.writeFieldBegin(CHILD_ID_FIELD_DESC);
          oprot.writeString(struct.childId);
          oprot.writeFieldEnd();
        }
        if (struct.groupId != null) {
          oprot.writeFieldBegin(GROUP_ID_FIELD_DESC);
          oprot.writeString(struct.groupId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class removeChildGroupFromParentGroup_argsTupleSchemeFactory implements SchemeFactory {
      public removeChildGroupFromParentGroup_argsTupleScheme getScheme() {
        return new removeChildGroupFromParentGroup_argsTupleScheme();
      }
    }

    private static class removeChildGroupFromParentGroup_argsTupleScheme extends TupleScheme<removeChildGroupFromParentGroup_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, removeChildGroupFromParentGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.childId);
        oprot.writeString(struct.groupId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, removeChildGroupFromParentGroup_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.childId = iprot.readString();
        struct.setChildIdIsSet(true);
        struct.groupId = iprot.readString();
        struct.setGroupIdIsSet(true);
      }
    }

  }

  public static class removeChildGroupFromParentGroup_result implements org.apache.thrift.TBase<removeChildGroupFromParentGroup_result, removeChildGroupFromParentGroup_result._Fields>, java.io.Serializable, Cloneable, Comparable<removeChildGroupFromParentGroup_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("removeChildGroupFromParentGroup_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new removeChildGroupFromParentGroup_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new removeChildGroupFromParentGroup_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(removeChildGroupFromParentGroup_result.class, metaDataMap);
    }

    public removeChildGroupFromParentGroup_result() {
    }

    public removeChildGroupFromParentGroup_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public removeChildGroupFromParentGroup_result(removeChildGroupFromParentGroup_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public removeChildGroupFromParentGroup_result deepCopy() {
      return new removeChildGroupFromParentGroup_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public removeChildGroupFromParentGroup_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public removeChildGroupFromParentGroup_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof removeChildGroupFromParentGroup_result)
        return this.equals((removeChildGroupFromParentGroup_result)that);
      return false;
    }

    public boolean equals(removeChildGroupFromParentGroup_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(removeChildGroupFromParentGroup_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("removeChildGroupFromParentGroup_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class removeChildGroupFromParentGroup_resultStandardSchemeFactory implements SchemeFactory {
      public removeChildGroupFromParentGroup_resultStandardScheme getScheme() {
        return new removeChildGroupFromParentGroup_resultStandardScheme();
      }
    }

    private static class removeChildGroupFromParentGroup_resultStandardScheme extends StandardScheme<removeChildGroupFromParentGroup_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, removeChildGroupFromParentGroup_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, removeChildGroupFromParentGroup_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class removeChildGroupFromParentGroup_resultTupleSchemeFactory implements SchemeFactory {
      public removeChildGroupFromParentGroup_resultTupleScheme getScheme() {
        return new removeChildGroupFromParentGroup_resultTupleScheme();
      }
    }

    private static class removeChildGroupFromParentGroup_resultTupleScheme extends TupleScheme<removeChildGroupFromParentGroup_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, removeChildGroupFromParentGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, removeChildGroupFromParentGroup_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getAllMemberGroupsForUser_args implements org.apache.thrift.TBase<getAllMemberGroupsForUser_args, getAllMemberGroupsForUser_args._Fields>, java.io.Serializable, Cloneable, Comparable<getAllMemberGroupsForUser_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getAllMemberGroupsForUser_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField USER_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("userId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getAllMemberGroupsForUser_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getAllMemberGroupsForUser_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String userId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      USER_ID((short)2, "userId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // USER_ID
            return USER_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.USER_ID, new org.apache.thrift.meta_data.FieldMetaData("userId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getAllMemberGroupsForUser_args.class, metaDataMap);
    }

    public getAllMemberGroupsForUser_args() {
    }

    public getAllMemberGroupsForUser_args(
      String domainId,
      String userId)
    {
      this();
      this.domainId = domainId;
      this.userId = userId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getAllMemberGroupsForUser_args(getAllMemberGroupsForUser_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetUserId()) {
        this.userId = other.userId;
      }
    }

    public getAllMemberGroupsForUser_args deepCopy() {
      return new getAllMemberGroupsForUser_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.userId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getAllMemberGroupsForUser_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getUserId() {
      return this.userId;
    }

    public getAllMemberGroupsForUser_args setUserId(String userId) {
      this.userId = userId;
      return this;
    }

    public void unsetUserId() {
      this.userId = null;
    }

    /** Returns true if field userId is set (has been assigned a value) and false otherwise */
    public boolean isSetUserId() {
      return this.userId != null;
    }

    public void setUserIdIsSet(boolean value) {
      if (!value) {
        this.userId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case USER_ID:
        if (value == null) {
          unsetUserId();
        } else {
          setUserId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case USER_ID:
        return getUserId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case USER_ID:
        return isSetUserId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getAllMemberGroupsForUser_args)
        return this.equals((getAllMemberGroupsForUser_args)that);
      return false;
    }

    public boolean equals(getAllMemberGroupsForUser_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_userId = true && this.isSetUserId();
      boolean that_present_userId = true && that.isSetUserId();
      if (this_present_userId || that_present_userId) {
        if (!(this_present_userId && that_present_userId))
          return false;
        if (!this.userId.equals(that.userId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_userId = true && (isSetUserId());
      list.add(present_userId);
      if (present_userId)
        list.add(userId);

      return list.hashCode();
    }

    @Override
    public int compareTo(getAllMemberGroupsForUser_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetUserId()).compareTo(other.isSetUserId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetUserId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.userId, other.userId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getAllMemberGroupsForUser_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("userId:");
      if (this.userId == null) {
        sb.append("null");
      } else {
        sb.append(this.userId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (userId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'userId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getAllMemberGroupsForUser_argsStandardSchemeFactory implements SchemeFactory {
      public getAllMemberGroupsForUser_argsStandardScheme getScheme() {
        return new getAllMemberGroupsForUser_argsStandardScheme();
      }
    }

    private static class getAllMemberGroupsForUser_argsStandardScheme extends StandardScheme<getAllMemberGroupsForUser_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getAllMemberGroupsForUser_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // USER_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.userId = iprot.readString();
                struct.setUserIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getAllMemberGroupsForUser_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.userId != null) {
          oprot.writeFieldBegin(USER_ID_FIELD_DESC);
          oprot.writeString(struct.userId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getAllMemberGroupsForUser_argsTupleSchemeFactory implements SchemeFactory {
      public getAllMemberGroupsForUser_argsTupleScheme getScheme() {
        return new getAllMemberGroupsForUser_argsTupleScheme();
      }
    }

    private static class getAllMemberGroupsForUser_argsTupleScheme extends TupleScheme<getAllMemberGroupsForUser_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getAllMemberGroupsForUser_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.userId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getAllMemberGroupsForUser_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.userId = iprot.readString();
        struct.setUserIdIsSet(true);
      }
    }

  }

  public static class getAllMemberGroupsForUser_result implements org.apache.thrift.TBase<getAllMemberGroupsForUser_result, getAllMemberGroupsForUser_result._Fields>, java.io.Serializable, Cloneable, Comparable<getAllMemberGroupsForUser_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getAllMemberGroupsForUser_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getAllMemberGroupsForUser_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getAllMemberGroupsForUser_resultTupleSchemeFactory());
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.UserGroup.class))));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getAllMemberGroupsForUser_result.class, metaDataMap);
    }

    public getAllMemberGroupsForUser_result() {
    }

    public getAllMemberGroupsForUser_result(
      List<org.apache.airavata.sharing.registry.models.UserGroup> success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getAllMemberGroupsForUser_result(getAllMemberGroupsForUser_result other) {
      if (other.isSetSuccess()) {
        List<org.apache.airavata.sharing.registry.models.UserGroup> __this__success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>(other.success.size());
        for (org.apache.airavata.sharing.registry.models.UserGroup other_element : other.success) {
          __this__success.add(new org.apache.airavata.sharing.registry.models.UserGroup(other_element));
        }
        this.success = __this__success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getAllMemberGroupsForUser_result deepCopy() {
      return new getAllMemberGroupsForUser_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public int getSuccessSize() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<org.apache.airavata.sharing.registry.models.UserGroup> getSuccessIterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void addToSuccess(org.apache.airavata.sharing.registry.models.UserGroup elem) {
      if (this.success == null) {
        this.success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>();
      }
      this.success.add(elem);
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> getSuccess() {
      return this.success;
    }

    public getAllMemberGroupsForUser_result setSuccess(List<org.apache.airavata.sharing.registry.models.UserGroup> success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getAllMemberGroupsForUser_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((List<org.apache.airavata.sharing.registry.models.UserGroup>)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getAllMemberGroupsForUser_result)
        return this.equals((getAllMemberGroupsForUser_result)that);
      return false;
    }

    public boolean equals(getAllMemberGroupsForUser_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getAllMemberGroupsForUser_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getAllMemberGroupsForUser_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getAllMemberGroupsForUser_resultStandardSchemeFactory implements SchemeFactory {
      public getAllMemberGroupsForUser_resultStandardScheme getScheme() {
        return new getAllMemberGroupsForUser_resultStandardScheme();
      }
    }

    private static class getAllMemberGroupsForUser_resultStandardScheme extends StandardScheme<getAllMemberGroupsForUser_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getAllMemberGroupsForUser_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list64 = iprot.readListBegin();
                  struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>(_list64.size);
                  org.apache.airavata.sharing.registry.models.UserGroup _elem65;
                  for (int _i66 = 0; _i66 < _list64.size; ++_i66)
                  {
                    _elem65 = new org.apache.airavata.sharing.registry.models.UserGroup();
                    _elem65.read(iprot);
                    struct.success.add(_elem65);
                  }
                  iprot.readListEnd();
                }
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getAllMemberGroupsForUser_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (org.apache.airavata.sharing.registry.models.UserGroup _iter67 : struct.success)
            {
              _iter67.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getAllMemberGroupsForUser_resultTupleSchemeFactory implements SchemeFactory {
      public getAllMemberGroupsForUser_resultTupleScheme getScheme() {
        return new getAllMemberGroupsForUser_resultTupleScheme();
      }
    }

    private static class getAllMemberGroupsForUser_resultTupleScheme extends TupleScheme<getAllMemberGroupsForUser_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getAllMemberGroupsForUser_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          {
            oprot.writeI32(struct.success.size());
            for (org.apache.airavata.sharing.registry.models.UserGroup _iter68 : struct.success)
            {
              _iter68.write(oprot);
            }
          }
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getAllMemberGroupsForUser_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list69 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>(_list69.size);
            org.apache.airavata.sharing.registry.models.UserGroup _elem70;
            for (int _i71 = 0; _i71 < _list69.size; ++_i71)
            {
              _elem70 = new org.apache.airavata.sharing.registry.models.UserGroup();
              _elem70.read(iprot);
              struct.success.add(_elem70);
            }
          }
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class createEntityType_args implements org.apache.thrift.TBase<createEntityType_args, createEntityType_args._Fields>, java.io.Serializable, Cloneable, Comparable<createEntityType_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createEntityType_args");

    private static final org.apache.thrift.protocol.TField ENTITY_TYPE_FIELD_DESC = new org.apache.thrift.protocol.TField("entityType", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new createEntityType_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new createEntityType_argsTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.EntityType entityType; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      ENTITY_TYPE((short)1, "entityType");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // ENTITY_TYPE
            return ENTITY_TYPE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.ENTITY_TYPE, new org.apache.thrift.meta_data.FieldMetaData("entityType", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.EntityType.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createEntityType_args.class, metaDataMap);
    }

    public createEntityType_args() {
    }

    public createEntityType_args(
      org.apache.airavata.sharing.registry.models.EntityType entityType)
    {
      this();
      this.entityType = entityType;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public createEntityType_args(createEntityType_args other) {
      if (other.isSetEntityType()) {
        this.entityType = new org.apache.airavata.sharing.registry.models.EntityType(other.entityType);
      }
    }

    public createEntityType_args deepCopy() {
      return new createEntityType_args(this);
    }

    @Override
    public void clear() {
      this.entityType = null;
    }

    public org.apache.airavata.sharing.registry.models.EntityType getEntityType() {
      return this.entityType;
    }

    public createEntityType_args setEntityType(org.apache.airavata.sharing.registry.models.EntityType entityType) {
      this.entityType = entityType;
      return this;
    }

    public void unsetEntityType() {
      this.entityType = null;
    }

    /** Returns true if field entityType is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityType() {
      return this.entityType != null;
    }

    public void setEntityTypeIsSet(boolean value) {
      if (!value) {
        this.entityType = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case ENTITY_TYPE:
        if (value == null) {
          unsetEntityType();
        } else {
          setEntityType((org.apache.airavata.sharing.registry.models.EntityType)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case ENTITY_TYPE:
        return getEntityType();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case ENTITY_TYPE:
        return isSetEntityType();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof createEntityType_args)
        return this.equals((createEntityType_args)that);
      return false;
    }

    public boolean equals(createEntityType_args that) {
      if (that == null)
        return false;

      boolean this_present_entityType = true && this.isSetEntityType();
      boolean that_present_entityType = true && that.isSetEntityType();
      if (this_present_entityType || that_present_entityType) {
        if (!(this_present_entityType && that_present_entityType))
          return false;
        if (!this.entityType.equals(that.entityType))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_entityType = true && (isSetEntityType());
      list.add(present_entityType);
      if (present_entityType)
        list.add(entityType);

      return list.hashCode();
    }

    @Override
    public int compareTo(createEntityType_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetEntityType()).compareTo(other.isSetEntityType());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityType()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityType, other.entityType);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("createEntityType_args(");
      boolean first = true;

      sb.append("entityType:");
      if (this.entityType == null) {
        sb.append("null");
      } else {
        sb.append(this.entityType);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (entityType == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityType' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
      if (entityType != null) {
        entityType.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class createEntityType_argsStandardSchemeFactory implements SchemeFactory {
      public createEntityType_argsStandardScheme getScheme() {
        return new createEntityType_argsStandardScheme();
      }
    }

    private static class createEntityType_argsStandardScheme extends StandardScheme<createEntityType_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, createEntityType_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // ENTITY_TYPE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.entityType = new org.apache.airavata.sharing.registry.models.EntityType();
                struct.entityType.read(iprot);
                struct.setEntityTypeIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, createEntityType_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.entityType != null) {
          oprot.writeFieldBegin(ENTITY_TYPE_FIELD_DESC);
          struct.entityType.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class createEntityType_argsTupleSchemeFactory implements SchemeFactory {
      public createEntityType_argsTupleScheme getScheme() {
        return new createEntityType_argsTupleScheme();
      }
    }

    private static class createEntityType_argsTupleScheme extends TupleScheme<createEntityType_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, createEntityType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        struct.entityType.write(oprot);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, createEntityType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.entityType = new org.apache.airavata.sharing.registry.models.EntityType();
        struct.entityType.read(iprot);
        struct.setEntityTypeIsSet(true);
      }
    }

  }

  public static class createEntityType_result implements org.apache.thrift.TBase<createEntityType_result, createEntityType_result._Fields>, java.io.Serializable, Cloneable, Comparable<createEntityType_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createEntityType_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);
    private static final org.apache.thrift.protocol.TField DEE_FIELD_DESC = new org.apache.thrift.protocol.TField("dee", org.apache.thrift.protocol.TType.STRUCT, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new createEntityType_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new createEntityType_resultTupleSchemeFactory());
    }

    public String success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required
    public org.apache.airavata.sharing.registry.models.DuplicateEntryException dee; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre"),
      DEE((short)2, "dee");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          case 2: // DEE
            return DEE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      tmpMap.put(_Fields.DEE, new org.apache.thrift.meta_data.FieldMetaData("dee", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createEntityType_result.class, metaDataMap);
    }

    public createEntityType_result() {
    }

    public createEntityType_result(
      String success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre,
      org.apache.airavata.sharing.registry.models.DuplicateEntryException dee)
    {
      this();
      this.success = success;
      this.sre = sre;
      this.dee = dee;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public createEntityType_result(createEntityType_result other) {
      if (other.isSetSuccess()) {
        this.success = other.success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
      if (other.isSetDee()) {
        this.dee = new org.apache.airavata.sharing.registry.models.DuplicateEntryException(other.dee);
      }
    }

    public createEntityType_result deepCopy() {
      return new createEntityType_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
      this.dee = null;
    }

    public String getSuccess() {
      return this.success;
    }

    public createEntityType_result setSuccess(String success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public createEntityType_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.DuplicateEntryException getDee() {
      return this.dee;
    }

    public createEntityType_result setDee(org.apache.airavata.sharing.registry.models.DuplicateEntryException dee) {
      this.dee = dee;
      return this;
    }

    public void unsetDee() {
      this.dee = null;
    }

    /** Returns true if field dee is set (has been assigned a value) and false otherwise */
    public boolean isSetDee() {
      return this.dee != null;
    }

    public void setDeeIsSet(boolean value) {
      if (!value) {
        this.dee = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((String)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      case DEE:
        if (value == null) {
          unsetDee();
        } else {
          setDee((org.apache.airavata.sharing.registry.models.DuplicateEntryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      case DEE:
        return getDee();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      case DEE:
        return isSetDee();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof createEntityType_result)
        return this.equals((createEntityType_result)that);
      return false;
    }

    public boolean equals(createEntityType_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      boolean this_present_dee = true && this.isSetDee();
      boolean that_present_dee = true && that.isSetDee();
      if (this_present_dee || that_present_dee) {
        if (!(this_present_dee && that_present_dee))
          return false;
        if (!this.dee.equals(that.dee))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      boolean present_dee = true && (isSetDee());
      list.add(present_dee);
      if (present_dee)
        list.add(dee);

      return list.hashCode();
    }

    @Override
    public int compareTo(createEntityType_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetDee()).compareTo(other.isSetDee());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDee()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.dee, other.dee);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("createEntityType_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("dee:");
      if (this.dee == null) {
        sb.append("null");
      } else {
        sb.append(this.dee);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class createEntityType_resultStandardSchemeFactory implements SchemeFactory {
      public createEntityType_resultStandardScheme getScheme() {
        return new createEntityType_resultStandardScheme();
      }
    }

    private static class createEntityType_resultStandardScheme extends StandardScheme<createEntityType_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, createEntityType_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.success = iprot.readString();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // DEE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.dee = new org.apache.airavata.sharing.registry.models.DuplicateEntryException();
                struct.dee.read(iprot);
                struct.setDeeIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, createEntityType_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeString(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.dee != null) {
          oprot.writeFieldBegin(DEE_FIELD_DESC);
          struct.dee.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class createEntityType_resultTupleSchemeFactory implements SchemeFactory {
      public createEntityType_resultTupleScheme getScheme() {
        return new createEntityType_resultTupleScheme();
      }
    }

    private static class createEntityType_resultTupleScheme extends TupleScheme<createEntityType_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, createEntityType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        if (struct.isSetDee()) {
          optionals.set(2);
        }
        oprot.writeBitSet(optionals, 3);
        if (struct.isSetSuccess()) {
          oprot.writeString(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
        if (struct.isSetDee()) {
          struct.dee.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, createEntityType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(3);
        if (incoming.get(0)) {
          struct.success = iprot.readString();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
        if (incoming.get(2)) {
          struct.dee = new org.apache.airavata.sharing.registry.models.DuplicateEntryException();
          struct.dee.read(iprot);
          struct.setDeeIsSet(true);
        }
      }
    }

  }

  public static class updateEntityType_args implements org.apache.thrift.TBase<updateEntityType_args, updateEntityType_args._Fields>, java.io.Serializable, Cloneable, Comparable<updateEntityType_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updateEntityType_args");

    private static final org.apache.thrift.protocol.TField ENTITY_TYPE_FIELD_DESC = new org.apache.thrift.protocol.TField("entityType", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updateEntityType_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updateEntityType_argsTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.EntityType entityType; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      ENTITY_TYPE((short)1, "entityType");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // ENTITY_TYPE
            return ENTITY_TYPE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.ENTITY_TYPE, new org.apache.thrift.meta_data.FieldMetaData("entityType", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.EntityType.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updateEntityType_args.class, metaDataMap);
    }

    public updateEntityType_args() {
    }

    public updateEntityType_args(
      org.apache.airavata.sharing.registry.models.EntityType entityType)
    {
      this();
      this.entityType = entityType;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updateEntityType_args(updateEntityType_args other) {
      if (other.isSetEntityType()) {
        this.entityType = new org.apache.airavata.sharing.registry.models.EntityType(other.entityType);
      }
    }

    public updateEntityType_args deepCopy() {
      return new updateEntityType_args(this);
    }

    @Override
    public void clear() {
      this.entityType = null;
    }

    public org.apache.airavata.sharing.registry.models.EntityType getEntityType() {
      return this.entityType;
    }

    public updateEntityType_args setEntityType(org.apache.airavata.sharing.registry.models.EntityType entityType) {
      this.entityType = entityType;
      return this;
    }

    public void unsetEntityType() {
      this.entityType = null;
    }

    /** Returns true if field entityType is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityType() {
      return this.entityType != null;
    }

    public void setEntityTypeIsSet(boolean value) {
      if (!value) {
        this.entityType = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case ENTITY_TYPE:
        if (value == null) {
          unsetEntityType();
        } else {
          setEntityType((org.apache.airavata.sharing.registry.models.EntityType)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case ENTITY_TYPE:
        return getEntityType();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case ENTITY_TYPE:
        return isSetEntityType();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updateEntityType_args)
        return this.equals((updateEntityType_args)that);
      return false;
    }

    public boolean equals(updateEntityType_args that) {
      if (that == null)
        return false;

      boolean this_present_entityType = true && this.isSetEntityType();
      boolean that_present_entityType = true && that.isSetEntityType();
      if (this_present_entityType || that_present_entityType) {
        if (!(this_present_entityType && that_present_entityType))
          return false;
        if (!this.entityType.equals(that.entityType))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_entityType = true && (isSetEntityType());
      list.add(present_entityType);
      if (present_entityType)
        list.add(entityType);

      return list.hashCode();
    }

    @Override
    public int compareTo(updateEntityType_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetEntityType()).compareTo(other.isSetEntityType());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityType()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityType, other.entityType);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updateEntityType_args(");
      boolean first = true;

      sb.append("entityType:");
      if (this.entityType == null) {
        sb.append("null");
      } else {
        sb.append(this.entityType);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (entityType == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityType' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
      if (entityType != null) {
        entityType.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updateEntityType_argsStandardSchemeFactory implements SchemeFactory {
      public updateEntityType_argsStandardScheme getScheme() {
        return new updateEntityType_argsStandardScheme();
      }
    }

    private static class updateEntityType_argsStandardScheme extends StandardScheme<updateEntityType_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updateEntityType_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // ENTITY_TYPE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.entityType = new org.apache.airavata.sharing.registry.models.EntityType();
                struct.entityType.read(iprot);
                struct.setEntityTypeIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updateEntityType_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.entityType != null) {
          oprot.writeFieldBegin(ENTITY_TYPE_FIELD_DESC);
          struct.entityType.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updateEntityType_argsTupleSchemeFactory implements SchemeFactory {
      public updateEntityType_argsTupleScheme getScheme() {
        return new updateEntityType_argsTupleScheme();
      }
    }

    private static class updateEntityType_argsTupleScheme extends TupleScheme<updateEntityType_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updateEntityType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        struct.entityType.write(oprot);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updateEntityType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.entityType = new org.apache.airavata.sharing.registry.models.EntityType();
        struct.entityType.read(iprot);
        struct.setEntityTypeIsSet(true);
      }
    }

  }

  public static class updateEntityType_result implements org.apache.thrift.TBase<updateEntityType_result, updateEntityType_result._Fields>, java.io.Serializable, Cloneable, Comparable<updateEntityType_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updateEntityType_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updateEntityType_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updateEntityType_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updateEntityType_result.class, metaDataMap);
    }

    public updateEntityType_result() {
    }

    public updateEntityType_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updateEntityType_result(updateEntityType_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public updateEntityType_result deepCopy() {
      return new updateEntityType_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public updateEntityType_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public updateEntityType_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updateEntityType_result)
        return this.equals((updateEntityType_result)that);
      return false;
    }

    public boolean equals(updateEntityType_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(updateEntityType_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updateEntityType_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updateEntityType_resultStandardSchemeFactory implements SchemeFactory {
      public updateEntityType_resultStandardScheme getScheme() {
        return new updateEntityType_resultStandardScheme();
      }
    }

    private static class updateEntityType_resultStandardScheme extends StandardScheme<updateEntityType_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updateEntityType_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updateEntityType_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updateEntityType_resultTupleSchemeFactory implements SchemeFactory {
      public updateEntityType_resultTupleScheme getScheme() {
        return new updateEntityType_resultTupleScheme();
      }
    }

    private static class updateEntityType_resultTupleScheme extends TupleScheme<updateEntityType_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updateEntityType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updateEntityType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class isEntityTypeExists_args implements org.apache.thrift.TBase<isEntityTypeExists_args, isEntityTypeExists_args._Fields>, java.io.Serializable, Cloneable, Comparable<isEntityTypeExists_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("isEntityTypeExists_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField ENTITY_TYPE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("entityTypeId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new isEntityTypeExists_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new isEntityTypeExists_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String entityTypeId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      ENTITY_TYPE_ID((short)2, "entityTypeId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // ENTITY_TYPE_ID
            return ENTITY_TYPE_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.ENTITY_TYPE_ID, new org.apache.thrift.meta_data.FieldMetaData("entityTypeId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(isEntityTypeExists_args.class, metaDataMap);
    }

    public isEntityTypeExists_args() {
    }

    public isEntityTypeExists_args(
      String domainId,
      String entityTypeId)
    {
      this();
      this.domainId = domainId;
      this.entityTypeId = entityTypeId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public isEntityTypeExists_args(isEntityTypeExists_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetEntityTypeId()) {
        this.entityTypeId = other.entityTypeId;
      }
    }

    public isEntityTypeExists_args deepCopy() {
      return new isEntityTypeExists_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.entityTypeId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public isEntityTypeExists_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getEntityTypeId() {
      return this.entityTypeId;
    }

    public isEntityTypeExists_args setEntityTypeId(String entityTypeId) {
      this.entityTypeId = entityTypeId;
      return this;
    }

    public void unsetEntityTypeId() {
      this.entityTypeId = null;
    }

    /** Returns true if field entityTypeId is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityTypeId() {
      return this.entityTypeId != null;
    }

    public void setEntityTypeIdIsSet(boolean value) {
      if (!value) {
        this.entityTypeId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case ENTITY_TYPE_ID:
        if (value == null) {
          unsetEntityTypeId();
        } else {
          setEntityTypeId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case ENTITY_TYPE_ID:
        return getEntityTypeId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case ENTITY_TYPE_ID:
        return isSetEntityTypeId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof isEntityTypeExists_args)
        return this.equals((isEntityTypeExists_args)that);
      return false;
    }

    public boolean equals(isEntityTypeExists_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_entityTypeId = true && this.isSetEntityTypeId();
      boolean that_present_entityTypeId = true && that.isSetEntityTypeId();
      if (this_present_entityTypeId || that_present_entityTypeId) {
        if (!(this_present_entityTypeId && that_present_entityTypeId))
          return false;
        if (!this.entityTypeId.equals(that.entityTypeId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_entityTypeId = true && (isSetEntityTypeId());
      list.add(present_entityTypeId);
      if (present_entityTypeId)
        list.add(entityTypeId);

      return list.hashCode();
    }

    @Override
    public int compareTo(isEntityTypeExists_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetEntityTypeId()).compareTo(other.isSetEntityTypeId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityTypeId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityTypeId, other.entityTypeId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("isEntityTypeExists_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("entityTypeId:");
      if (this.entityTypeId == null) {
        sb.append("null");
      } else {
        sb.append(this.entityTypeId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (entityTypeId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityTypeId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class isEntityTypeExists_argsStandardSchemeFactory implements SchemeFactory {
      public isEntityTypeExists_argsStandardScheme getScheme() {
        return new isEntityTypeExists_argsStandardScheme();
      }
    }

    private static class isEntityTypeExists_argsStandardScheme extends StandardScheme<isEntityTypeExists_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, isEntityTypeExists_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ENTITY_TYPE_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.entityTypeId = iprot.readString();
                struct.setEntityTypeIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, isEntityTypeExists_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.entityTypeId != null) {
          oprot.writeFieldBegin(ENTITY_TYPE_ID_FIELD_DESC);
          oprot.writeString(struct.entityTypeId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class isEntityTypeExists_argsTupleSchemeFactory implements SchemeFactory {
      public isEntityTypeExists_argsTupleScheme getScheme() {
        return new isEntityTypeExists_argsTupleScheme();
      }
    }

    private static class isEntityTypeExists_argsTupleScheme extends TupleScheme<isEntityTypeExists_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, isEntityTypeExists_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.entityTypeId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, isEntityTypeExists_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.entityTypeId = iprot.readString();
        struct.setEntityTypeIdIsSet(true);
      }
    }

  }

  public static class isEntityTypeExists_result implements org.apache.thrift.TBase<isEntityTypeExists_result, isEntityTypeExists_result._Fields>, java.io.Serializable, Cloneable, Comparable<isEntityTypeExists_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("isEntityTypeExists_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new isEntityTypeExists_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new isEntityTypeExists_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(isEntityTypeExists_result.class, metaDataMap);
    }

    public isEntityTypeExists_result() {
    }

    public isEntityTypeExists_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public isEntityTypeExists_result(isEntityTypeExists_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public isEntityTypeExists_result deepCopy() {
      return new isEntityTypeExists_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public isEntityTypeExists_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public isEntityTypeExists_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof isEntityTypeExists_result)
        return this.equals((isEntityTypeExists_result)that);
      return false;
    }

    public boolean equals(isEntityTypeExists_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(isEntityTypeExists_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("isEntityTypeExists_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class isEntityTypeExists_resultStandardSchemeFactory implements SchemeFactory {
      public isEntityTypeExists_resultStandardScheme getScheme() {
        return new isEntityTypeExists_resultStandardScheme();
      }
    }

    private static class isEntityTypeExists_resultStandardScheme extends StandardScheme<isEntityTypeExists_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, isEntityTypeExists_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, isEntityTypeExists_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class isEntityTypeExists_resultTupleSchemeFactory implements SchemeFactory {
      public isEntityTypeExists_resultTupleScheme getScheme() {
        return new isEntityTypeExists_resultTupleScheme();
      }
    }

    private static class isEntityTypeExists_resultTupleScheme extends TupleScheme<isEntityTypeExists_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, isEntityTypeExists_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, isEntityTypeExists_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class deleteEntityType_args implements org.apache.thrift.TBase<deleteEntityType_args, deleteEntityType_args._Fields>, java.io.Serializable, Cloneable, Comparable<deleteEntityType_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deleteEntityType_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField ENTITY_TYPE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("entityTypeId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deleteEntityType_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deleteEntityType_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String entityTypeId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      ENTITY_TYPE_ID((short)2, "entityTypeId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // ENTITY_TYPE_ID
            return ENTITY_TYPE_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.ENTITY_TYPE_ID, new org.apache.thrift.meta_data.FieldMetaData("entityTypeId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deleteEntityType_args.class, metaDataMap);
    }

    public deleteEntityType_args() {
    }

    public deleteEntityType_args(
      String domainId,
      String entityTypeId)
    {
      this();
      this.domainId = domainId;
      this.entityTypeId = entityTypeId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deleteEntityType_args(deleteEntityType_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetEntityTypeId()) {
        this.entityTypeId = other.entityTypeId;
      }
    }

    public deleteEntityType_args deepCopy() {
      return new deleteEntityType_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.entityTypeId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public deleteEntityType_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getEntityTypeId() {
      return this.entityTypeId;
    }

    public deleteEntityType_args setEntityTypeId(String entityTypeId) {
      this.entityTypeId = entityTypeId;
      return this;
    }

    public void unsetEntityTypeId() {
      this.entityTypeId = null;
    }

    /** Returns true if field entityTypeId is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityTypeId() {
      return this.entityTypeId != null;
    }

    public void setEntityTypeIdIsSet(boolean value) {
      if (!value) {
        this.entityTypeId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case ENTITY_TYPE_ID:
        if (value == null) {
          unsetEntityTypeId();
        } else {
          setEntityTypeId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case ENTITY_TYPE_ID:
        return getEntityTypeId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case ENTITY_TYPE_ID:
        return isSetEntityTypeId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deleteEntityType_args)
        return this.equals((deleteEntityType_args)that);
      return false;
    }

    public boolean equals(deleteEntityType_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_entityTypeId = true && this.isSetEntityTypeId();
      boolean that_present_entityTypeId = true && that.isSetEntityTypeId();
      if (this_present_entityTypeId || that_present_entityTypeId) {
        if (!(this_present_entityTypeId && that_present_entityTypeId))
          return false;
        if (!this.entityTypeId.equals(that.entityTypeId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_entityTypeId = true && (isSetEntityTypeId());
      list.add(present_entityTypeId);
      if (present_entityTypeId)
        list.add(entityTypeId);

      return list.hashCode();
    }

    @Override
    public int compareTo(deleteEntityType_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetEntityTypeId()).compareTo(other.isSetEntityTypeId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityTypeId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityTypeId, other.entityTypeId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deleteEntityType_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("entityTypeId:");
      if (this.entityTypeId == null) {
        sb.append("null");
      } else {
        sb.append(this.entityTypeId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (entityTypeId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityTypeId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deleteEntityType_argsStandardSchemeFactory implements SchemeFactory {
      public deleteEntityType_argsStandardScheme getScheme() {
        return new deleteEntityType_argsStandardScheme();
      }
    }

    private static class deleteEntityType_argsStandardScheme extends StandardScheme<deleteEntityType_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deleteEntityType_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ENTITY_TYPE_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.entityTypeId = iprot.readString();
                struct.setEntityTypeIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deleteEntityType_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.entityTypeId != null) {
          oprot.writeFieldBegin(ENTITY_TYPE_ID_FIELD_DESC);
          oprot.writeString(struct.entityTypeId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deleteEntityType_argsTupleSchemeFactory implements SchemeFactory {
      public deleteEntityType_argsTupleScheme getScheme() {
        return new deleteEntityType_argsTupleScheme();
      }
    }

    private static class deleteEntityType_argsTupleScheme extends TupleScheme<deleteEntityType_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deleteEntityType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.entityTypeId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deleteEntityType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.entityTypeId = iprot.readString();
        struct.setEntityTypeIdIsSet(true);
      }
    }

  }

  public static class deleteEntityType_result implements org.apache.thrift.TBase<deleteEntityType_result, deleteEntityType_result._Fields>, java.io.Serializable, Cloneable, Comparable<deleteEntityType_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deleteEntityType_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deleteEntityType_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deleteEntityType_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deleteEntityType_result.class, metaDataMap);
    }

    public deleteEntityType_result() {
    }

    public deleteEntityType_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deleteEntityType_result(deleteEntityType_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public deleteEntityType_result deepCopy() {
      return new deleteEntityType_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public deleteEntityType_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public deleteEntityType_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deleteEntityType_result)
        return this.equals((deleteEntityType_result)that);
      return false;
    }

    public boolean equals(deleteEntityType_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(deleteEntityType_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deleteEntityType_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deleteEntityType_resultStandardSchemeFactory implements SchemeFactory {
      public deleteEntityType_resultStandardScheme getScheme() {
        return new deleteEntityType_resultStandardScheme();
      }
    }

    private static class deleteEntityType_resultStandardScheme extends StandardScheme<deleteEntityType_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deleteEntityType_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deleteEntityType_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deleteEntityType_resultTupleSchemeFactory implements SchemeFactory {
      public deleteEntityType_resultTupleScheme getScheme() {
        return new deleteEntityType_resultTupleScheme();
      }
    }

    private static class deleteEntityType_resultTupleScheme extends TupleScheme<deleteEntityType_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deleteEntityType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deleteEntityType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getEntityType_args implements org.apache.thrift.TBase<getEntityType_args, getEntityType_args._Fields>, java.io.Serializable, Cloneable, Comparable<getEntityType_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getEntityType_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField ENTITY_TYPE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("entityTypeId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getEntityType_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getEntityType_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String entityTypeId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      ENTITY_TYPE_ID((short)2, "entityTypeId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // ENTITY_TYPE_ID
            return ENTITY_TYPE_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.ENTITY_TYPE_ID, new org.apache.thrift.meta_data.FieldMetaData("entityTypeId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getEntityType_args.class, metaDataMap);
    }

    public getEntityType_args() {
    }

    public getEntityType_args(
      String domainId,
      String entityTypeId)
    {
      this();
      this.domainId = domainId;
      this.entityTypeId = entityTypeId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getEntityType_args(getEntityType_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetEntityTypeId()) {
        this.entityTypeId = other.entityTypeId;
      }
    }

    public getEntityType_args deepCopy() {
      return new getEntityType_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.entityTypeId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getEntityType_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getEntityTypeId() {
      return this.entityTypeId;
    }

    public getEntityType_args setEntityTypeId(String entityTypeId) {
      this.entityTypeId = entityTypeId;
      return this;
    }

    public void unsetEntityTypeId() {
      this.entityTypeId = null;
    }

    /** Returns true if field entityTypeId is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityTypeId() {
      return this.entityTypeId != null;
    }

    public void setEntityTypeIdIsSet(boolean value) {
      if (!value) {
        this.entityTypeId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case ENTITY_TYPE_ID:
        if (value == null) {
          unsetEntityTypeId();
        } else {
          setEntityTypeId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case ENTITY_TYPE_ID:
        return getEntityTypeId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case ENTITY_TYPE_ID:
        return isSetEntityTypeId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getEntityType_args)
        return this.equals((getEntityType_args)that);
      return false;
    }

    public boolean equals(getEntityType_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_entityTypeId = true && this.isSetEntityTypeId();
      boolean that_present_entityTypeId = true && that.isSetEntityTypeId();
      if (this_present_entityTypeId || that_present_entityTypeId) {
        if (!(this_present_entityTypeId && that_present_entityTypeId))
          return false;
        if (!this.entityTypeId.equals(that.entityTypeId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_entityTypeId = true && (isSetEntityTypeId());
      list.add(present_entityTypeId);
      if (present_entityTypeId)
        list.add(entityTypeId);

      return list.hashCode();
    }

    @Override
    public int compareTo(getEntityType_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetEntityTypeId()).compareTo(other.isSetEntityTypeId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityTypeId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityTypeId, other.entityTypeId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getEntityType_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("entityTypeId:");
      if (this.entityTypeId == null) {
        sb.append("null");
      } else {
        sb.append(this.entityTypeId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (entityTypeId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityTypeId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getEntityType_argsStandardSchemeFactory implements SchemeFactory {
      public getEntityType_argsStandardScheme getScheme() {
        return new getEntityType_argsStandardScheme();
      }
    }

    private static class getEntityType_argsStandardScheme extends StandardScheme<getEntityType_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getEntityType_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ENTITY_TYPE_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.entityTypeId = iprot.readString();
                struct.setEntityTypeIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getEntityType_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.entityTypeId != null) {
          oprot.writeFieldBegin(ENTITY_TYPE_ID_FIELD_DESC);
          oprot.writeString(struct.entityTypeId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getEntityType_argsTupleSchemeFactory implements SchemeFactory {
      public getEntityType_argsTupleScheme getScheme() {
        return new getEntityType_argsTupleScheme();
      }
    }

    private static class getEntityType_argsTupleScheme extends TupleScheme<getEntityType_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getEntityType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.entityTypeId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getEntityType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.entityTypeId = iprot.readString();
        struct.setEntityTypeIdIsSet(true);
      }
    }

  }

  public static class getEntityType_result implements org.apache.thrift.TBase<getEntityType_result, getEntityType_result._Fields>, java.io.Serializable, Cloneable, Comparable<getEntityType_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getEntityType_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getEntityType_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getEntityType_resultTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.EntityType success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.EntityType.class)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getEntityType_result.class, metaDataMap);
    }

    public getEntityType_result() {
    }

    public getEntityType_result(
      org.apache.airavata.sharing.registry.models.EntityType success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getEntityType_result(getEntityType_result other) {
      if (other.isSetSuccess()) {
        this.success = new org.apache.airavata.sharing.registry.models.EntityType(other.success);
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getEntityType_result deepCopy() {
      return new getEntityType_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public org.apache.airavata.sharing.registry.models.EntityType getSuccess() {
      return this.success;
    }

    public getEntityType_result setSuccess(org.apache.airavata.sharing.registry.models.EntityType success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getEntityType_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((org.apache.airavata.sharing.registry.models.EntityType)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getEntityType_result)
        return this.equals((getEntityType_result)that);
      return false;
    }

    public boolean equals(getEntityType_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getEntityType_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getEntityType_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getEntityType_resultStandardSchemeFactory implements SchemeFactory {
      public getEntityType_resultStandardScheme getScheme() {
        return new getEntityType_resultStandardScheme();
      }
    }

    private static class getEntityType_resultStandardScheme extends StandardScheme<getEntityType_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getEntityType_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new org.apache.airavata.sharing.registry.models.EntityType();
                struct.success.read(iprot);
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getEntityType_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getEntityType_resultTupleSchemeFactory implements SchemeFactory {
      public getEntityType_resultTupleScheme getScheme() {
        return new getEntityType_resultTupleScheme();
      }
    }

    private static class getEntityType_resultTupleScheme extends TupleScheme<getEntityType_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getEntityType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          struct.success.write(oprot);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getEntityType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = new org.apache.airavata.sharing.registry.models.EntityType();
          struct.success.read(iprot);
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getEntityTypes_args implements org.apache.thrift.TBase<getEntityTypes_args, getEntityTypes_args._Fields>, java.io.Serializable, Cloneable, Comparable<getEntityTypes_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getEntityTypes_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField OFFSET_FIELD_DESC = new org.apache.thrift.protocol.TField("offset", org.apache.thrift.protocol.TType.I32, (short)2);
    private static final org.apache.thrift.protocol.TField LIMIT_FIELD_DESC = new org.apache.thrift.protocol.TField("limit", org.apache.thrift.protocol.TType.I32, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getEntityTypes_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getEntityTypes_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public int offset; // required
    public int limit; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      OFFSET((short)2, "offset"),
      LIMIT((short)3, "limit");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // OFFSET
            return OFFSET;
          case 3: // LIMIT
            return LIMIT;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __OFFSET_ISSET_ID = 0;
    private static final int __LIMIT_ISSET_ID = 1;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.OFFSET, new org.apache.thrift.meta_data.FieldMetaData("offset", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      tmpMap.put(_Fields.LIMIT, new org.apache.thrift.meta_data.FieldMetaData("limit", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getEntityTypes_args.class, metaDataMap);
    }

    public getEntityTypes_args() {
    }

    public getEntityTypes_args(
      String domainId,
      int offset,
      int limit)
    {
      this();
      this.domainId = domainId;
      this.offset = offset;
      setOffsetIsSet(true);
      this.limit = limit;
      setLimitIsSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getEntityTypes_args(getEntityTypes_args other) {
      __isset_bitfield = other.__isset_bitfield;
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      this.offset = other.offset;
      this.limit = other.limit;
    }

    public getEntityTypes_args deepCopy() {
      return new getEntityTypes_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      setOffsetIsSet(false);
      this.offset = 0;
      setLimitIsSet(false);
      this.limit = 0;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getEntityTypes_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public int getOffset() {
      return this.offset;
    }

    public getEntityTypes_args setOffset(int offset) {
      this.offset = offset;
      setOffsetIsSet(true);
      return this;
    }

    public void unsetOffset() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    /** Returns true if field offset is set (has been assigned a value) and false otherwise */
    public boolean isSetOffset() {
      return EncodingUtils.testBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    public void setOffsetIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __OFFSET_ISSET_ID, value);
    }

    public int getLimit() {
      return this.limit;
    }

    public getEntityTypes_args setLimit(int limit) {
      this.limit = limit;
      setLimitIsSet(true);
      return this;
    }

    public void unsetLimit() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    /** Returns true if field limit is set (has been assigned a value) and false otherwise */
    public boolean isSetLimit() {
      return EncodingUtils.testBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    public void setLimitIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __LIMIT_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case OFFSET:
        if (value == null) {
          unsetOffset();
        } else {
          setOffset((Integer)value);
        }
        break;

      case LIMIT:
        if (value == null) {
          unsetLimit();
        } else {
          setLimit((Integer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case OFFSET:
        return getOffset();

      case LIMIT:
        return getLimit();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case OFFSET:
        return isSetOffset();
      case LIMIT:
        return isSetLimit();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getEntityTypes_args)
        return this.equals((getEntityTypes_args)that);
      return false;
    }

    public boolean equals(getEntityTypes_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_offset = true;
      boolean that_present_offset = true;
      if (this_present_offset || that_present_offset) {
        if (!(this_present_offset && that_present_offset))
          return false;
        if (this.offset != that.offset)
          return false;
      }

      boolean this_present_limit = true;
      boolean that_present_limit = true;
      if (this_present_limit || that_present_limit) {
        if (!(this_present_limit && that_present_limit))
          return false;
        if (this.limit != that.limit)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_offset = true;
      list.add(present_offset);
      if (present_offset)
        list.add(offset);

      boolean present_limit = true;
      list.add(present_limit);
      if (present_limit)
        list.add(limit);

      return list.hashCode();
    }

    @Override
    public int compareTo(getEntityTypes_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetOffset()).compareTo(other.isSetOffset());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetOffset()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.offset, other.offset);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetLimit()).compareTo(other.isSetLimit());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetLimit()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.limit, other.limit);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getEntityTypes_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("offset:");
      sb.append(this.offset);
      first = false;
      if (!first) sb.append(", ");
      sb.append("limit:");
      sb.append(this.limit);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      // alas, we cannot check 'offset' because it's a primitive and you chose the non-beans generator.
      // alas, we cannot check 'limit' because it's a primitive and you chose the non-beans generator.
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getEntityTypes_argsStandardSchemeFactory implements SchemeFactory {
      public getEntityTypes_argsStandardScheme getScheme() {
        return new getEntityTypes_argsStandardScheme();
      }
    }

    private static class getEntityTypes_argsStandardScheme extends StandardScheme<getEntityTypes_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getEntityTypes_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // OFFSET
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.offset = iprot.readI32();
                struct.setOffsetIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // LIMIT
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.limit = iprot.readI32();
                struct.setLimitIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        if (!struct.isSetOffset()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'offset' was not found in serialized data! Struct: " + toString());
        }
        if (!struct.isSetLimit()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'limit' was not found in serialized data! Struct: " + toString());
        }
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getEntityTypes_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldBegin(OFFSET_FIELD_DESC);
        oprot.writeI32(struct.offset);
        oprot.writeFieldEnd();
        oprot.writeFieldBegin(LIMIT_FIELD_DESC);
        oprot.writeI32(struct.limit);
        oprot.writeFieldEnd();
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getEntityTypes_argsTupleSchemeFactory implements SchemeFactory {
      public getEntityTypes_argsTupleScheme getScheme() {
        return new getEntityTypes_argsTupleScheme();
      }
    }

    private static class getEntityTypes_argsTupleScheme extends TupleScheme<getEntityTypes_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getEntityTypes_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeI32(struct.offset);
        oprot.writeI32(struct.limit);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getEntityTypes_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.offset = iprot.readI32();
        struct.setOffsetIsSet(true);
        struct.limit = iprot.readI32();
        struct.setLimitIsSet(true);
      }
    }

  }

  public static class getEntityTypes_result implements org.apache.thrift.TBase<getEntityTypes_result, getEntityTypes_result._Fields>, java.io.Serializable, Cloneable, Comparable<getEntityTypes_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getEntityTypes_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getEntityTypes_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getEntityTypes_resultTupleSchemeFactory());
    }

    public List<org.apache.airavata.sharing.registry.models.EntityType> success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.EntityType.class))));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getEntityTypes_result.class, metaDataMap);
    }

    public getEntityTypes_result() {
    }

    public getEntityTypes_result(
      List<org.apache.airavata.sharing.registry.models.EntityType> success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getEntityTypes_result(getEntityTypes_result other) {
      if (other.isSetSuccess()) {
        List<org.apache.airavata.sharing.registry.models.EntityType> __this__success = new ArrayList<org.apache.airavata.sharing.registry.models.EntityType>(other.success.size());
        for (org.apache.airavata.sharing.registry.models.EntityType other_element : other.success) {
          __this__success.add(new org.apache.airavata.sharing.registry.models.EntityType(other_element));
        }
        this.success = __this__success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getEntityTypes_result deepCopy() {
      return new getEntityTypes_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public int getSuccessSize() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<org.apache.airavata.sharing.registry.models.EntityType> getSuccessIterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void addToSuccess(org.apache.airavata.sharing.registry.models.EntityType elem) {
      if (this.success == null) {
        this.success = new ArrayList<org.apache.airavata.sharing.registry.models.EntityType>();
      }
      this.success.add(elem);
    }

    public List<org.apache.airavata.sharing.registry.models.EntityType> getSuccess() {
      return this.success;
    }

    public getEntityTypes_result setSuccess(List<org.apache.airavata.sharing.registry.models.EntityType> success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getEntityTypes_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((List<org.apache.airavata.sharing.registry.models.EntityType>)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getEntityTypes_result)
        return this.equals((getEntityTypes_result)that);
      return false;
    }

    public boolean equals(getEntityTypes_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getEntityTypes_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getEntityTypes_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getEntityTypes_resultStandardSchemeFactory implements SchemeFactory {
      public getEntityTypes_resultStandardScheme getScheme() {
        return new getEntityTypes_resultStandardScheme();
      }
    }

    private static class getEntityTypes_resultStandardScheme extends StandardScheme<getEntityTypes_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getEntityTypes_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list72 = iprot.readListBegin();
                  struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.EntityType>(_list72.size);
                  org.apache.airavata.sharing.registry.models.EntityType _elem73;
                  for (int _i74 = 0; _i74 < _list72.size; ++_i74)
                  {
                    _elem73 = new org.apache.airavata.sharing.registry.models.EntityType();
                    _elem73.read(iprot);
                    struct.success.add(_elem73);
                  }
                  iprot.readListEnd();
                }
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getEntityTypes_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (org.apache.airavata.sharing.registry.models.EntityType _iter75 : struct.success)
            {
              _iter75.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getEntityTypes_resultTupleSchemeFactory implements SchemeFactory {
      public getEntityTypes_resultTupleScheme getScheme() {
        return new getEntityTypes_resultTupleScheme();
      }
    }

    private static class getEntityTypes_resultTupleScheme extends TupleScheme<getEntityTypes_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getEntityTypes_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          {
            oprot.writeI32(struct.success.size());
            for (org.apache.airavata.sharing.registry.models.EntityType _iter76 : struct.success)
            {
              _iter76.write(oprot);
            }
          }
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getEntityTypes_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list77 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.EntityType>(_list77.size);
            org.apache.airavata.sharing.registry.models.EntityType _elem78;
            for (int _i79 = 0; _i79 < _list77.size; ++_i79)
            {
              _elem78 = new org.apache.airavata.sharing.registry.models.EntityType();
              _elem78.read(iprot);
              struct.success.add(_elem78);
            }
          }
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class createEntity_args implements org.apache.thrift.TBase<createEntity_args, createEntity_args._Fields>, java.io.Serializable, Cloneable, Comparable<createEntity_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createEntity_args");

    private static final org.apache.thrift.protocol.TField ENTITY_FIELD_DESC = new org.apache.thrift.protocol.TField("entity", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new createEntity_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new createEntity_argsTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.Entity entity; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      ENTITY((short)1, "entity");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // ENTITY
            return ENTITY;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.ENTITY, new org.apache.thrift.meta_data.FieldMetaData("entity", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.Entity.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createEntity_args.class, metaDataMap);
    }

    public createEntity_args() {
    }

    public createEntity_args(
      org.apache.airavata.sharing.registry.models.Entity entity)
    {
      this();
      this.entity = entity;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public createEntity_args(createEntity_args other) {
      if (other.isSetEntity()) {
        this.entity = new org.apache.airavata.sharing.registry.models.Entity(other.entity);
      }
    }

    public createEntity_args deepCopy() {
      return new createEntity_args(this);
    }

    @Override
    public void clear() {
      this.entity = null;
    }

    public org.apache.airavata.sharing.registry.models.Entity getEntity() {
      return this.entity;
    }

    public createEntity_args setEntity(org.apache.airavata.sharing.registry.models.Entity entity) {
      this.entity = entity;
      return this;
    }

    public void unsetEntity() {
      this.entity = null;
    }

    /** Returns true if field entity is set (has been assigned a value) and false otherwise */
    public boolean isSetEntity() {
      return this.entity != null;
    }

    public void setEntityIsSet(boolean value) {
      if (!value) {
        this.entity = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case ENTITY:
        if (value == null) {
          unsetEntity();
        } else {
          setEntity((org.apache.airavata.sharing.registry.models.Entity)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case ENTITY:
        return getEntity();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case ENTITY:
        return isSetEntity();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof createEntity_args)
        return this.equals((createEntity_args)that);
      return false;
    }

    public boolean equals(createEntity_args that) {
      if (that == null)
        return false;

      boolean this_present_entity = true && this.isSetEntity();
      boolean that_present_entity = true && that.isSetEntity();
      if (this_present_entity || that_present_entity) {
        if (!(this_present_entity && that_present_entity))
          return false;
        if (!this.entity.equals(that.entity))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_entity = true && (isSetEntity());
      list.add(present_entity);
      if (present_entity)
        list.add(entity);

      return list.hashCode();
    }

    @Override
    public int compareTo(createEntity_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetEntity()).compareTo(other.isSetEntity());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntity()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entity, other.entity);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("createEntity_args(");
      boolean first = true;

      sb.append("entity:");
      if (this.entity == null) {
        sb.append("null");
      } else {
        sb.append(this.entity);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (entity == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entity' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
      if (entity != null) {
        entity.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class createEntity_argsStandardSchemeFactory implements SchemeFactory {
      public createEntity_argsStandardScheme getScheme() {
        return new createEntity_argsStandardScheme();
      }
    }

    private static class createEntity_argsStandardScheme extends StandardScheme<createEntity_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, createEntity_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // ENTITY
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.entity = new org.apache.airavata.sharing.registry.models.Entity();
                struct.entity.read(iprot);
                struct.setEntityIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, createEntity_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.entity != null) {
          oprot.writeFieldBegin(ENTITY_FIELD_DESC);
          struct.entity.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class createEntity_argsTupleSchemeFactory implements SchemeFactory {
      public createEntity_argsTupleScheme getScheme() {
        return new createEntity_argsTupleScheme();
      }
    }

    private static class createEntity_argsTupleScheme extends TupleScheme<createEntity_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, createEntity_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        struct.entity.write(oprot);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, createEntity_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.entity = new org.apache.airavata.sharing.registry.models.Entity();
        struct.entity.read(iprot);
        struct.setEntityIsSet(true);
      }
    }

  }

  public static class createEntity_result implements org.apache.thrift.TBase<createEntity_result, createEntity_result._Fields>, java.io.Serializable, Cloneable, Comparable<createEntity_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createEntity_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new createEntity_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new createEntity_resultTupleSchemeFactory());
    }

    public String success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createEntity_result.class, metaDataMap);
    }

    public createEntity_result() {
    }

    public createEntity_result(
      String success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public createEntity_result(createEntity_result other) {
      if (other.isSetSuccess()) {
        this.success = other.success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public createEntity_result deepCopy() {
      return new createEntity_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public String getSuccess() {
      return this.success;
    }

    public createEntity_result setSuccess(String success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public createEntity_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((String)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof createEntity_result)
        return this.equals((createEntity_result)that);
      return false;
    }

    public boolean equals(createEntity_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(createEntity_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("createEntity_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class createEntity_resultStandardSchemeFactory implements SchemeFactory {
      public createEntity_resultStandardScheme getScheme() {
        return new createEntity_resultStandardScheme();
      }
    }

    private static class createEntity_resultStandardScheme extends StandardScheme<createEntity_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, createEntity_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.success = iprot.readString();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, createEntity_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeString(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class createEntity_resultTupleSchemeFactory implements SchemeFactory {
      public createEntity_resultTupleScheme getScheme() {
        return new createEntity_resultTupleScheme();
      }
    }

    private static class createEntity_resultTupleScheme extends TupleScheme<createEntity_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, createEntity_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeString(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, createEntity_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readString();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class updateEntity_args implements org.apache.thrift.TBase<updateEntity_args, updateEntity_args._Fields>, java.io.Serializable, Cloneable, Comparable<updateEntity_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updateEntity_args");

    private static final org.apache.thrift.protocol.TField ENTITY_FIELD_DESC = new org.apache.thrift.protocol.TField("entity", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updateEntity_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updateEntity_argsTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.Entity entity; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      ENTITY((short)1, "entity");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // ENTITY
            return ENTITY;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.ENTITY, new org.apache.thrift.meta_data.FieldMetaData("entity", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.Entity.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updateEntity_args.class, metaDataMap);
    }

    public updateEntity_args() {
    }

    public updateEntity_args(
      org.apache.airavata.sharing.registry.models.Entity entity)
    {
      this();
      this.entity = entity;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updateEntity_args(updateEntity_args other) {
      if (other.isSetEntity()) {
        this.entity = new org.apache.airavata.sharing.registry.models.Entity(other.entity);
      }
    }

    public updateEntity_args deepCopy() {
      return new updateEntity_args(this);
    }

    @Override
    public void clear() {
      this.entity = null;
    }

    public org.apache.airavata.sharing.registry.models.Entity getEntity() {
      return this.entity;
    }

    public updateEntity_args setEntity(org.apache.airavata.sharing.registry.models.Entity entity) {
      this.entity = entity;
      return this;
    }

    public void unsetEntity() {
      this.entity = null;
    }

    /** Returns true if field entity is set (has been assigned a value) and false otherwise */
    public boolean isSetEntity() {
      return this.entity != null;
    }

    public void setEntityIsSet(boolean value) {
      if (!value) {
        this.entity = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case ENTITY:
        if (value == null) {
          unsetEntity();
        } else {
          setEntity((org.apache.airavata.sharing.registry.models.Entity)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case ENTITY:
        return getEntity();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case ENTITY:
        return isSetEntity();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updateEntity_args)
        return this.equals((updateEntity_args)that);
      return false;
    }

    public boolean equals(updateEntity_args that) {
      if (that == null)
        return false;

      boolean this_present_entity = true && this.isSetEntity();
      boolean that_present_entity = true && that.isSetEntity();
      if (this_present_entity || that_present_entity) {
        if (!(this_present_entity && that_present_entity))
          return false;
        if (!this.entity.equals(that.entity))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_entity = true && (isSetEntity());
      list.add(present_entity);
      if (present_entity)
        list.add(entity);

      return list.hashCode();
    }

    @Override
    public int compareTo(updateEntity_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetEntity()).compareTo(other.isSetEntity());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntity()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entity, other.entity);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updateEntity_args(");
      boolean first = true;

      sb.append("entity:");
      if (this.entity == null) {
        sb.append("null");
      } else {
        sb.append(this.entity);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (entity == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entity' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
      if (entity != null) {
        entity.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updateEntity_argsStandardSchemeFactory implements SchemeFactory {
      public updateEntity_argsStandardScheme getScheme() {
        return new updateEntity_argsStandardScheme();
      }
    }

    private static class updateEntity_argsStandardScheme extends StandardScheme<updateEntity_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updateEntity_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // ENTITY
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.entity = new org.apache.airavata.sharing.registry.models.Entity();
                struct.entity.read(iprot);
                struct.setEntityIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updateEntity_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.entity != null) {
          oprot.writeFieldBegin(ENTITY_FIELD_DESC);
          struct.entity.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updateEntity_argsTupleSchemeFactory implements SchemeFactory {
      public updateEntity_argsTupleScheme getScheme() {
        return new updateEntity_argsTupleScheme();
      }
    }

    private static class updateEntity_argsTupleScheme extends TupleScheme<updateEntity_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updateEntity_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        struct.entity.write(oprot);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updateEntity_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.entity = new org.apache.airavata.sharing.registry.models.Entity();
        struct.entity.read(iprot);
        struct.setEntityIsSet(true);
      }
    }

  }

  public static class updateEntity_result implements org.apache.thrift.TBase<updateEntity_result, updateEntity_result._Fields>, java.io.Serializable, Cloneable, Comparable<updateEntity_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updateEntity_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updateEntity_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updateEntity_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updateEntity_result.class, metaDataMap);
    }

    public updateEntity_result() {
    }

    public updateEntity_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updateEntity_result(updateEntity_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public updateEntity_result deepCopy() {
      return new updateEntity_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public updateEntity_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public updateEntity_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updateEntity_result)
        return this.equals((updateEntity_result)that);
      return false;
    }

    public boolean equals(updateEntity_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(updateEntity_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updateEntity_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updateEntity_resultStandardSchemeFactory implements SchemeFactory {
      public updateEntity_resultStandardScheme getScheme() {
        return new updateEntity_resultStandardScheme();
      }
    }

    private static class updateEntity_resultStandardScheme extends StandardScheme<updateEntity_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updateEntity_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updateEntity_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updateEntity_resultTupleSchemeFactory implements SchemeFactory {
      public updateEntity_resultTupleScheme getScheme() {
        return new updateEntity_resultTupleScheme();
      }
    }

    private static class updateEntity_resultTupleScheme extends TupleScheme<updateEntity_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updateEntity_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updateEntity_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class isEntityExists_args implements org.apache.thrift.TBase<isEntityExists_args, isEntityExists_args._Fields>, java.io.Serializable, Cloneable, Comparable<isEntityExists_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("isEntityExists_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField ENTITY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("entityId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new isEntityExists_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new isEntityExists_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String entityId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      ENTITY_ID((short)2, "entityId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // ENTITY_ID
            return ENTITY_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.ENTITY_ID, new org.apache.thrift.meta_data.FieldMetaData("entityId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(isEntityExists_args.class, metaDataMap);
    }

    public isEntityExists_args() {
    }

    public isEntityExists_args(
      String domainId,
      String entityId)
    {
      this();
      this.domainId = domainId;
      this.entityId = entityId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public isEntityExists_args(isEntityExists_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetEntityId()) {
        this.entityId = other.entityId;
      }
    }

    public isEntityExists_args deepCopy() {
      return new isEntityExists_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.entityId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public isEntityExists_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getEntityId() {
      return this.entityId;
    }

    public isEntityExists_args setEntityId(String entityId) {
      this.entityId = entityId;
      return this;
    }

    public void unsetEntityId() {
      this.entityId = null;
    }

    /** Returns true if field entityId is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityId() {
      return this.entityId != null;
    }

    public void setEntityIdIsSet(boolean value) {
      if (!value) {
        this.entityId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case ENTITY_ID:
        if (value == null) {
          unsetEntityId();
        } else {
          setEntityId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case ENTITY_ID:
        return getEntityId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case ENTITY_ID:
        return isSetEntityId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof isEntityExists_args)
        return this.equals((isEntityExists_args)that);
      return false;
    }

    public boolean equals(isEntityExists_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_entityId = true && this.isSetEntityId();
      boolean that_present_entityId = true && that.isSetEntityId();
      if (this_present_entityId || that_present_entityId) {
        if (!(this_present_entityId && that_present_entityId))
          return false;
        if (!this.entityId.equals(that.entityId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_entityId = true && (isSetEntityId());
      list.add(present_entityId);
      if (present_entityId)
        list.add(entityId);

      return list.hashCode();
    }

    @Override
    public int compareTo(isEntityExists_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetEntityId()).compareTo(other.isSetEntityId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityId, other.entityId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("isEntityExists_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("entityId:");
      if (this.entityId == null) {
        sb.append("null");
      } else {
        sb.append(this.entityId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (entityId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class isEntityExists_argsStandardSchemeFactory implements SchemeFactory {
      public isEntityExists_argsStandardScheme getScheme() {
        return new isEntityExists_argsStandardScheme();
      }
    }

    private static class isEntityExists_argsStandardScheme extends StandardScheme<isEntityExists_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, isEntityExists_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ENTITY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.entityId = iprot.readString();
                struct.setEntityIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, isEntityExists_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.entityId != null) {
          oprot.writeFieldBegin(ENTITY_ID_FIELD_DESC);
          oprot.writeString(struct.entityId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class isEntityExists_argsTupleSchemeFactory implements SchemeFactory {
      public isEntityExists_argsTupleScheme getScheme() {
        return new isEntityExists_argsTupleScheme();
      }
    }

    private static class isEntityExists_argsTupleScheme extends TupleScheme<isEntityExists_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, isEntityExists_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.entityId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, isEntityExists_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.entityId = iprot.readString();
        struct.setEntityIdIsSet(true);
      }
    }

  }

  public static class isEntityExists_result implements org.apache.thrift.TBase<isEntityExists_result, isEntityExists_result._Fields>, java.io.Serializable, Cloneable, Comparable<isEntityExists_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("isEntityExists_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new isEntityExists_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new isEntityExists_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(isEntityExists_result.class, metaDataMap);
    }

    public isEntityExists_result() {
    }

    public isEntityExists_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public isEntityExists_result(isEntityExists_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public isEntityExists_result deepCopy() {
      return new isEntityExists_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public isEntityExists_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public isEntityExists_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof isEntityExists_result)
        return this.equals((isEntityExists_result)that);
      return false;
    }

    public boolean equals(isEntityExists_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(isEntityExists_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("isEntityExists_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class isEntityExists_resultStandardSchemeFactory implements SchemeFactory {
      public isEntityExists_resultStandardScheme getScheme() {
        return new isEntityExists_resultStandardScheme();
      }
    }

    private static class isEntityExists_resultStandardScheme extends StandardScheme<isEntityExists_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, isEntityExists_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, isEntityExists_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class isEntityExists_resultTupleSchemeFactory implements SchemeFactory {
      public isEntityExists_resultTupleScheme getScheme() {
        return new isEntityExists_resultTupleScheme();
      }
    }

    private static class isEntityExists_resultTupleScheme extends TupleScheme<isEntityExists_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, isEntityExists_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, isEntityExists_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class deleteEntity_args implements org.apache.thrift.TBase<deleteEntity_args, deleteEntity_args._Fields>, java.io.Serializable, Cloneable, Comparable<deleteEntity_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deleteEntity_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField ENTITY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("entityId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deleteEntity_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deleteEntity_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String entityId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      ENTITY_ID((short)2, "entityId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // ENTITY_ID
            return ENTITY_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.ENTITY_ID, new org.apache.thrift.meta_data.FieldMetaData("entityId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deleteEntity_args.class, metaDataMap);
    }

    public deleteEntity_args() {
    }

    public deleteEntity_args(
      String domainId,
      String entityId)
    {
      this();
      this.domainId = domainId;
      this.entityId = entityId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deleteEntity_args(deleteEntity_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetEntityId()) {
        this.entityId = other.entityId;
      }
    }

    public deleteEntity_args deepCopy() {
      return new deleteEntity_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.entityId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public deleteEntity_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getEntityId() {
      return this.entityId;
    }

    public deleteEntity_args setEntityId(String entityId) {
      this.entityId = entityId;
      return this;
    }

    public void unsetEntityId() {
      this.entityId = null;
    }

    /** Returns true if field entityId is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityId() {
      return this.entityId != null;
    }

    public void setEntityIdIsSet(boolean value) {
      if (!value) {
        this.entityId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case ENTITY_ID:
        if (value == null) {
          unsetEntityId();
        } else {
          setEntityId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case ENTITY_ID:
        return getEntityId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case ENTITY_ID:
        return isSetEntityId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deleteEntity_args)
        return this.equals((deleteEntity_args)that);
      return false;
    }

    public boolean equals(deleteEntity_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_entityId = true && this.isSetEntityId();
      boolean that_present_entityId = true && that.isSetEntityId();
      if (this_present_entityId || that_present_entityId) {
        if (!(this_present_entityId && that_present_entityId))
          return false;
        if (!this.entityId.equals(that.entityId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_entityId = true && (isSetEntityId());
      list.add(present_entityId);
      if (present_entityId)
        list.add(entityId);

      return list.hashCode();
    }

    @Override
    public int compareTo(deleteEntity_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetEntityId()).compareTo(other.isSetEntityId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityId, other.entityId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deleteEntity_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("entityId:");
      if (this.entityId == null) {
        sb.append("null");
      } else {
        sb.append(this.entityId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (entityId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deleteEntity_argsStandardSchemeFactory implements SchemeFactory {
      public deleteEntity_argsStandardScheme getScheme() {
        return new deleteEntity_argsStandardScheme();
      }
    }

    private static class deleteEntity_argsStandardScheme extends StandardScheme<deleteEntity_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deleteEntity_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ENTITY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.entityId = iprot.readString();
                struct.setEntityIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deleteEntity_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.entityId != null) {
          oprot.writeFieldBegin(ENTITY_ID_FIELD_DESC);
          oprot.writeString(struct.entityId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deleteEntity_argsTupleSchemeFactory implements SchemeFactory {
      public deleteEntity_argsTupleScheme getScheme() {
        return new deleteEntity_argsTupleScheme();
      }
    }

    private static class deleteEntity_argsTupleScheme extends TupleScheme<deleteEntity_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deleteEntity_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.entityId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deleteEntity_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.entityId = iprot.readString();
        struct.setEntityIdIsSet(true);
      }
    }

  }

  public static class deleteEntity_result implements org.apache.thrift.TBase<deleteEntity_result, deleteEntity_result._Fields>, java.io.Serializable, Cloneable, Comparable<deleteEntity_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deleteEntity_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deleteEntity_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deleteEntity_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deleteEntity_result.class, metaDataMap);
    }

    public deleteEntity_result() {
    }

    public deleteEntity_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deleteEntity_result(deleteEntity_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public deleteEntity_result deepCopy() {
      return new deleteEntity_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public deleteEntity_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public deleteEntity_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deleteEntity_result)
        return this.equals((deleteEntity_result)that);
      return false;
    }

    public boolean equals(deleteEntity_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(deleteEntity_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deleteEntity_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deleteEntity_resultStandardSchemeFactory implements SchemeFactory {
      public deleteEntity_resultStandardScheme getScheme() {
        return new deleteEntity_resultStandardScheme();
      }
    }

    private static class deleteEntity_resultStandardScheme extends StandardScheme<deleteEntity_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deleteEntity_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deleteEntity_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deleteEntity_resultTupleSchemeFactory implements SchemeFactory {
      public deleteEntity_resultTupleScheme getScheme() {
        return new deleteEntity_resultTupleScheme();
      }
    }

    private static class deleteEntity_resultTupleScheme extends TupleScheme<deleteEntity_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deleteEntity_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deleteEntity_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getEntity_args implements org.apache.thrift.TBase<getEntity_args, getEntity_args._Fields>, java.io.Serializable, Cloneable, Comparable<getEntity_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getEntity_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField ENTITY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("entityId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getEntity_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getEntity_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String entityId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      ENTITY_ID((short)2, "entityId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // ENTITY_ID
            return ENTITY_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.ENTITY_ID, new org.apache.thrift.meta_data.FieldMetaData("entityId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getEntity_args.class, metaDataMap);
    }

    public getEntity_args() {
    }

    public getEntity_args(
      String domainId,
      String entityId)
    {
      this();
      this.domainId = domainId;
      this.entityId = entityId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getEntity_args(getEntity_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetEntityId()) {
        this.entityId = other.entityId;
      }
    }

    public getEntity_args deepCopy() {
      return new getEntity_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.entityId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getEntity_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getEntityId() {
      return this.entityId;
    }

    public getEntity_args setEntityId(String entityId) {
      this.entityId = entityId;
      return this;
    }

    public void unsetEntityId() {
      this.entityId = null;
    }

    /** Returns true if field entityId is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityId() {
      return this.entityId != null;
    }

    public void setEntityIdIsSet(boolean value) {
      if (!value) {
        this.entityId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case ENTITY_ID:
        if (value == null) {
          unsetEntityId();
        } else {
          setEntityId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case ENTITY_ID:
        return getEntityId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case ENTITY_ID:
        return isSetEntityId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getEntity_args)
        return this.equals((getEntity_args)that);
      return false;
    }

    public boolean equals(getEntity_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_entityId = true && this.isSetEntityId();
      boolean that_present_entityId = true && that.isSetEntityId();
      if (this_present_entityId || that_present_entityId) {
        if (!(this_present_entityId && that_present_entityId))
          return false;
        if (!this.entityId.equals(that.entityId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_entityId = true && (isSetEntityId());
      list.add(present_entityId);
      if (present_entityId)
        list.add(entityId);

      return list.hashCode();
    }

    @Override
    public int compareTo(getEntity_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetEntityId()).compareTo(other.isSetEntityId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityId, other.entityId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getEntity_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("entityId:");
      if (this.entityId == null) {
        sb.append("null");
      } else {
        sb.append(this.entityId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (entityId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getEntity_argsStandardSchemeFactory implements SchemeFactory {
      public getEntity_argsStandardScheme getScheme() {
        return new getEntity_argsStandardScheme();
      }
    }

    private static class getEntity_argsStandardScheme extends StandardScheme<getEntity_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getEntity_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ENTITY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.entityId = iprot.readString();
                struct.setEntityIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getEntity_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.entityId != null) {
          oprot.writeFieldBegin(ENTITY_ID_FIELD_DESC);
          oprot.writeString(struct.entityId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getEntity_argsTupleSchemeFactory implements SchemeFactory {
      public getEntity_argsTupleScheme getScheme() {
        return new getEntity_argsTupleScheme();
      }
    }

    private static class getEntity_argsTupleScheme extends TupleScheme<getEntity_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getEntity_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.entityId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getEntity_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.entityId = iprot.readString();
        struct.setEntityIdIsSet(true);
      }
    }

  }

  public static class getEntity_result implements org.apache.thrift.TBase<getEntity_result, getEntity_result._Fields>, java.io.Serializable, Cloneable, Comparable<getEntity_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getEntity_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getEntity_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getEntity_resultTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.Entity success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.Entity.class)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getEntity_result.class, metaDataMap);
    }

    public getEntity_result() {
    }

    public getEntity_result(
      org.apache.airavata.sharing.registry.models.Entity success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getEntity_result(getEntity_result other) {
      if (other.isSetSuccess()) {
        this.success = new org.apache.airavata.sharing.registry.models.Entity(other.success);
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getEntity_result deepCopy() {
      return new getEntity_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public org.apache.airavata.sharing.registry.models.Entity getSuccess() {
      return this.success;
    }

    public getEntity_result setSuccess(org.apache.airavata.sharing.registry.models.Entity success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getEntity_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((org.apache.airavata.sharing.registry.models.Entity)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getEntity_result)
        return this.equals((getEntity_result)that);
      return false;
    }

    public boolean equals(getEntity_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getEntity_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getEntity_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getEntity_resultStandardSchemeFactory implements SchemeFactory {
      public getEntity_resultStandardScheme getScheme() {
        return new getEntity_resultStandardScheme();
      }
    }

    private static class getEntity_resultStandardScheme extends StandardScheme<getEntity_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getEntity_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new org.apache.airavata.sharing.registry.models.Entity();
                struct.success.read(iprot);
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getEntity_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getEntity_resultTupleSchemeFactory implements SchemeFactory {
      public getEntity_resultTupleScheme getScheme() {
        return new getEntity_resultTupleScheme();
      }
    }

    private static class getEntity_resultTupleScheme extends TupleScheme<getEntity_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getEntity_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          struct.success.write(oprot);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getEntity_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = new org.apache.airavata.sharing.registry.models.Entity();
          struct.success.read(iprot);
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class searchEntities_args implements org.apache.thrift.TBase<searchEntities_args, searchEntities_args._Fields>, java.io.Serializable, Cloneable, Comparable<searchEntities_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("searchEntities_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField USER_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("userId", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField FILTERS_FIELD_DESC = new org.apache.thrift.protocol.TField("filters", org.apache.thrift.protocol.TType.LIST, (short)3);
    private static final org.apache.thrift.protocol.TField OFFSET_FIELD_DESC = new org.apache.thrift.protocol.TField("offset", org.apache.thrift.protocol.TType.I32, (short)4);
    private static final org.apache.thrift.protocol.TField LIMIT_FIELD_DESC = new org.apache.thrift.protocol.TField("limit", org.apache.thrift.protocol.TType.I32, (short)5);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new searchEntities_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new searchEntities_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String userId; // required
    public List<org.apache.airavata.sharing.registry.models.SearchCriteria> filters; // required
    public int offset; // required
    public int limit; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      USER_ID((short)2, "userId"),
      FILTERS((short)3, "filters"),
      OFFSET((short)4, "offset"),
      LIMIT((short)5, "limit");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // USER_ID
            return USER_ID;
          case 3: // FILTERS
            return FILTERS;
          case 4: // OFFSET
            return OFFSET;
          case 5: // LIMIT
            return LIMIT;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __OFFSET_ISSET_ID = 0;
    private static final int __LIMIT_ISSET_ID = 1;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.USER_ID, new org.apache.thrift.meta_data.FieldMetaData("userId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.FILTERS, new org.apache.thrift.meta_data.FieldMetaData("filters", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.SearchCriteria.class))));
      tmpMap.put(_Fields.OFFSET, new org.apache.thrift.meta_data.FieldMetaData("offset", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      tmpMap.put(_Fields.LIMIT, new org.apache.thrift.meta_data.FieldMetaData("limit", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(searchEntities_args.class, metaDataMap);
    }

    public searchEntities_args() {
    }

    public searchEntities_args(
      String domainId,
      String userId,
      List<org.apache.airavata.sharing.registry.models.SearchCriteria> filters,
      int offset,
      int limit)
    {
      this();
      this.domainId = domainId;
      this.userId = userId;
      this.filters = filters;
      this.offset = offset;
      setOffsetIsSet(true);
      this.limit = limit;
      setLimitIsSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public searchEntities_args(searchEntities_args other) {
      __isset_bitfield = other.__isset_bitfield;
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetUserId()) {
        this.userId = other.userId;
      }
      if (other.isSetFilters()) {
        List<org.apache.airavata.sharing.registry.models.SearchCriteria> __this__filters = new ArrayList<org.apache.airavata.sharing.registry.models.SearchCriteria>(other.filters.size());
        for (org.apache.airavata.sharing.registry.models.SearchCriteria other_element : other.filters) {
          __this__filters.add(new org.apache.airavata.sharing.registry.models.SearchCriteria(other_element));
        }
        this.filters = __this__filters;
      }
      this.offset = other.offset;
      this.limit = other.limit;
    }

    public searchEntities_args deepCopy() {
      return new searchEntities_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.userId = null;
      this.filters = null;
      setOffsetIsSet(false);
      this.offset = 0;
      setLimitIsSet(false);
      this.limit = 0;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public searchEntities_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getUserId() {
      return this.userId;
    }

    public searchEntities_args setUserId(String userId) {
      this.userId = userId;
      return this;
    }

    public void unsetUserId() {
      this.userId = null;
    }

    /** Returns true if field userId is set (has been assigned a value) and false otherwise */
    public boolean isSetUserId() {
      return this.userId != null;
    }

    public void setUserIdIsSet(boolean value) {
      if (!value) {
        this.userId = null;
      }
    }

    public int getFiltersSize() {
      return (this.filters == null) ? 0 : this.filters.size();
    }

    public java.util.Iterator<org.apache.airavata.sharing.registry.models.SearchCriteria> getFiltersIterator() {
      return (this.filters == null) ? null : this.filters.iterator();
    }

    public void addToFilters(org.apache.airavata.sharing.registry.models.SearchCriteria elem) {
      if (this.filters == null) {
        this.filters = new ArrayList<org.apache.airavata.sharing.registry.models.SearchCriteria>();
      }
      this.filters.add(elem);
    }

    public List<org.apache.airavata.sharing.registry.models.SearchCriteria> getFilters() {
      return this.filters;
    }

    public searchEntities_args setFilters(List<org.apache.airavata.sharing.registry.models.SearchCriteria> filters) {
      this.filters = filters;
      return this;
    }

    public void unsetFilters() {
      this.filters = null;
    }

    /** Returns true if field filters is set (has been assigned a value) and false otherwise */
    public boolean isSetFilters() {
      return this.filters != null;
    }

    public void setFiltersIsSet(boolean value) {
      if (!value) {
        this.filters = null;
      }
    }

    public int getOffset() {
      return this.offset;
    }

    public searchEntities_args setOffset(int offset) {
      this.offset = offset;
      setOffsetIsSet(true);
      return this;
    }

    public void unsetOffset() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    /** Returns true if field offset is set (has been assigned a value) and false otherwise */
    public boolean isSetOffset() {
      return EncodingUtils.testBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    public void setOffsetIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __OFFSET_ISSET_ID, value);
    }

    public int getLimit() {
      return this.limit;
    }

    public searchEntities_args setLimit(int limit) {
      this.limit = limit;
      setLimitIsSet(true);
      return this;
    }

    public void unsetLimit() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    /** Returns true if field limit is set (has been assigned a value) and false otherwise */
    public boolean isSetLimit() {
      return EncodingUtils.testBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    public void setLimitIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __LIMIT_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case USER_ID:
        if (value == null) {
          unsetUserId();
        } else {
          setUserId((String)value);
        }
        break;

      case FILTERS:
        if (value == null) {
          unsetFilters();
        } else {
          setFilters((List<org.apache.airavata.sharing.registry.models.SearchCriteria>)value);
        }
        break;

      case OFFSET:
        if (value == null) {
          unsetOffset();
        } else {
          setOffset((Integer)value);
        }
        break;

      case LIMIT:
        if (value == null) {
          unsetLimit();
        } else {
          setLimit((Integer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case USER_ID:
        return getUserId();

      case FILTERS:
        return getFilters();

      case OFFSET:
        return getOffset();

      case LIMIT:
        return getLimit();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case USER_ID:
        return isSetUserId();
      case FILTERS:
        return isSetFilters();
      case OFFSET:
        return isSetOffset();
      case LIMIT:
        return isSetLimit();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof searchEntities_args)
        return this.equals((searchEntities_args)that);
      return false;
    }

    public boolean equals(searchEntities_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_userId = true && this.isSetUserId();
      boolean that_present_userId = true && that.isSetUserId();
      if (this_present_userId || that_present_userId) {
        if (!(this_present_userId && that_present_userId))
          return false;
        if (!this.userId.equals(that.userId))
          return false;
      }

      boolean this_present_filters = true && this.isSetFilters();
      boolean that_present_filters = true && that.isSetFilters();
      if (this_present_filters || that_present_filters) {
        if (!(this_present_filters && that_present_filters))
          return false;
        if (!this.filters.equals(that.filters))
          return false;
      }

      boolean this_present_offset = true;
      boolean that_present_offset = true;
      if (this_present_offset || that_present_offset) {
        if (!(this_present_offset && that_present_offset))
          return false;
        if (this.offset != that.offset)
          return false;
      }

      boolean this_present_limit = true;
      boolean that_present_limit = true;
      if (this_present_limit || that_present_limit) {
        if (!(this_present_limit && that_present_limit))
          return false;
        if (this.limit != that.limit)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_userId = true && (isSetUserId());
      list.add(present_userId);
      if (present_userId)
        list.add(userId);

      boolean present_filters = true && (isSetFilters());
      list.add(present_filters);
      if (present_filters)
        list.add(filters);

      boolean present_offset = true;
      list.add(present_offset);
      if (present_offset)
        list.add(offset);

      boolean present_limit = true;
      list.add(present_limit);
      if (present_limit)
        list.add(limit);

      return list.hashCode();
    }

    @Override
    public int compareTo(searchEntities_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetUserId()).compareTo(other.isSetUserId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetUserId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.userId, other.userId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetFilters()).compareTo(other.isSetFilters());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetFilters()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.filters, other.filters);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetOffset()).compareTo(other.isSetOffset());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetOffset()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.offset, other.offset);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetLimit()).compareTo(other.isSetLimit());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetLimit()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.limit, other.limit);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("searchEntities_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("userId:");
      if (this.userId == null) {
        sb.append("null");
      } else {
        sb.append(this.userId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("filters:");
      if (this.filters == null) {
        sb.append("null");
      } else {
        sb.append(this.filters);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("offset:");
      sb.append(this.offset);
      first = false;
      if (!first) sb.append(", ");
      sb.append("limit:");
      sb.append(this.limit);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (userId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'userId' was not present! Struct: " + toString());
      }
      if (filters == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'filters' was not present! Struct: " + toString());
      }
      // alas, we cannot check 'offset' because it's a primitive and you chose the non-beans generator.
      // alas, we cannot check 'limit' because it's a primitive and you chose the non-beans generator.
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class searchEntities_argsStandardSchemeFactory implements SchemeFactory {
      public searchEntities_argsStandardScheme getScheme() {
        return new searchEntities_argsStandardScheme();
      }
    }

    private static class searchEntities_argsStandardScheme extends StandardScheme<searchEntities_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, searchEntities_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // USER_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.userId = iprot.readString();
                struct.setUserIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // FILTERS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list80 = iprot.readListBegin();
                  struct.filters = new ArrayList<org.apache.airavata.sharing.registry.models.SearchCriteria>(_list80.size);
                  org.apache.airavata.sharing.registry.models.SearchCriteria _elem81;
                  for (int _i82 = 0; _i82 < _list80.size; ++_i82)
                  {
                    _elem81 = new org.apache.airavata.sharing.registry.models.SearchCriteria();
                    _elem81.read(iprot);
                    struct.filters.add(_elem81);
                  }
                  iprot.readListEnd();
                }
                struct.setFiltersIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 4: // OFFSET
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.offset = iprot.readI32();
                struct.setOffsetIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 5: // LIMIT
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.limit = iprot.readI32();
                struct.setLimitIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        if (!struct.isSetOffset()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'offset' was not found in serialized data! Struct: " + toString());
        }
        if (!struct.isSetLimit()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'limit' was not found in serialized data! Struct: " + toString());
        }
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, searchEntities_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.userId != null) {
          oprot.writeFieldBegin(USER_ID_FIELD_DESC);
          oprot.writeString(struct.userId);
          oprot.writeFieldEnd();
        }
        if (struct.filters != null) {
          oprot.writeFieldBegin(FILTERS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.filters.size()));
            for (org.apache.airavata.sharing.registry.models.SearchCriteria _iter83 : struct.filters)
            {
              _iter83.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        oprot.writeFieldBegin(OFFSET_FIELD_DESC);
        oprot.writeI32(struct.offset);
        oprot.writeFieldEnd();
        oprot.writeFieldBegin(LIMIT_FIELD_DESC);
        oprot.writeI32(struct.limit);
        oprot.writeFieldEnd();
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class searchEntities_argsTupleSchemeFactory implements SchemeFactory {
      public searchEntities_argsTupleScheme getScheme() {
        return new searchEntities_argsTupleScheme();
      }
    }

    private static class searchEntities_argsTupleScheme extends TupleScheme<searchEntities_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, searchEntities_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.userId);
        {
          oprot.writeI32(struct.filters.size());
          for (org.apache.airavata.sharing.registry.models.SearchCriteria _iter84 : struct.filters)
          {
            _iter84.write(oprot);
          }
        }
        oprot.writeI32(struct.offset);
        oprot.writeI32(struct.limit);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, searchEntities_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.userId = iprot.readString();
        struct.setUserIdIsSet(true);
        {
          org.apache.thrift.protocol.TList _list85 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
          struct.filters = new ArrayList<org.apache.airavata.sharing.registry.models.SearchCriteria>(_list85.size);
          org.apache.airavata.sharing.registry.models.SearchCriteria _elem86;
          for (int _i87 = 0; _i87 < _list85.size; ++_i87)
          {
            _elem86 = new org.apache.airavata.sharing.registry.models.SearchCriteria();
            _elem86.read(iprot);
            struct.filters.add(_elem86);
          }
        }
        struct.setFiltersIsSet(true);
        struct.offset = iprot.readI32();
        struct.setOffsetIsSet(true);
        struct.limit = iprot.readI32();
        struct.setLimitIsSet(true);
      }
    }

  }

  public static class searchEntities_result implements org.apache.thrift.TBase<searchEntities_result, searchEntities_result._Fields>, java.io.Serializable, Cloneable, Comparable<searchEntities_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("searchEntities_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new searchEntities_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new searchEntities_resultTupleSchemeFactory());
    }

    public List<org.apache.airavata.sharing.registry.models.Entity> success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.Entity.class))));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(searchEntities_result.class, metaDataMap);
    }

    public searchEntities_result() {
    }

    public searchEntities_result(
      List<org.apache.airavata.sharing.registry.models.Entity> success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public searchEntities_result(searchEntities_result other) {
      if (other.isSetSuccess()) {
        List<org.apache.airavata.sharing.registry.models.Entity> __this__success = new ArrayList<org.apache.airavata.sharing.registry.models.Entity>(other.success.size());
        for (org.apache.airavata.sharing.registry.models.Entity other_element : other.success) {
          __this__success.add(new org.apache.airavata.sharing.registry.models.Entity(other_element));
        }
        this.success = __this__success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public searchEntities_result deepCopy() {
      return new searchEntities_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public int getSuccessSize() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<org.apache.airavata.sharing.registry.models.Entity> getSuccessIterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void addToSuccess(org.apache.airavata.sharing.registry.models.Entity elem) {
      if (this.success == null) {
        this.success = new ArrayList<org.apache.airavata.sharing.registry.models.Entity>();
      }
      this.success.add(elem);
    }

    public List<org.apache.airavata.sharing.registry.models.Entity> getSuccess() {
      return this.success;
    }

    public searchEntities_result setSuccess(List<org.apache.airavata.sharing.registry.models.Entity> success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public searchEntities_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((List<org.apache.airavata.sharing.registry.models.Entity>)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof searchEntities_result)
        return this.equals((searchEntities_result)that);
      return false;
    }

    public boolean equals(searchEntities_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(searchEntities_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("searchEntities_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class searchEntities_resultStandardSchemeFactory implements SchemeFactory {
      public searchEntities_resultStandardScheme getScheme() {
        return new searchEntities_resultStandardScheme();
      }
    }

    private static class searchEntities_resultStandardScheme extends StandardScheme<searchEntities_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, searchEntities_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list88 = iprot.readListBegin();
                  struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.Entity>(_list88.size);
                  org.apache.airavata.sharing.registry.models.Entity _elem89;
                  for (int _i90 = 0; _i90 < _list88.size; ++_i90)
                  {
                    _elem89 = new org.apache.airavata.sharing.registry.models.Entity();
                    _elem89.read(iprot);
                    struct.success.add(_elem89);
                  }
                  iprot.readListEnd();
                }
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, searchEntities_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (org.apache.airavata.sharing.registry.models.Entity _iter91 : struct.success)
            {
              _iter91.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class searchEntities_resultTupleSchemeFactory implements SchemeFactory {
      public searchEntities_resultTupleScheme getScheme() {
        return new searchEntities_resultTupleScheme();
      }
    }

    private static class searchEntities_resultTupleScheme extends TupleScheme<searchEntities_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, searchEntities_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          {
            oprot.writeI32(struct.success.size());
            for (org.apache.airavata.sharing.registry.models.Entity _iter92 : struct.success)
            {
              _iter92.write(oprot);
            }
          }
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, searchEntities_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list93 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.Entity>(_list93.size);
            org.apache.airavata.sharing.registry.models.Entity _elem94;
            for (int _i95 = 0; _i95 < _list93.size; ++_i95)
            {
              _elem94 = new org.apache.airavata.sharing.registry.models.Entity();
              _elem94.read(iprot);
              struct.success.add(_elem94);
            }
          }
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getListOfSharedUsers_args implements org.apache.thrift.TBase<getListOfSharedUsers_args, getListOfSharedUsers_args._Fields>, java.io.Serializable, Cloneable, Comparable<getListOfSharedUsers_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getListOfSharedUsers_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField ENTITY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("entityId", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField PERMISSION_TYPE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("permissionTypeId", org.apache.thrift.protocol.TType.STRING, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getListOfSharedUsers_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getListOfSharedUsers_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String entityId; // required
    public String permissionTypeId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      ENTITY_ID((short)2, "entityId"),
      PERMISSION_TYPE_ID((short)3, "permissionTypeId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // ENTITY_ID
            return ENTITY_ID;
          case 3: // PERMISSION_TYPE_ID
            return PERMISSION_TYPE_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.ENTITY_ID, new org.apache.thrift.meta_data.FieldMetaData("entityId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.PERMISSION_TYPE_ID, new org.apache.thrift.meta_data.FieldMetaData("permissionTypeId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getListOfSharedUsers_args.class, metaDataMap);
    }

    public getListOfSharedUsers_args() {
    }

    public getListOfSharedUsers_args(
      String domainId,
      String entityId,
      String permissionTypeId)
    {
      this();
      this.domainId = domainId;
      this.entityId = entityId;
      this.permissionTypeId = permissionTypeId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getListOfSharedUsers_args(getListOfSharedUsers_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetEntityId()) {
        this.entityId = other.entityId;
      }
      if (other.isSetPermissionTypeId()) {
        this.permissionTypeId = other.permissionTypeId;
      }
    }

    public getListOfSharedUsers_args deepCopy() {
      return new getListOfSharedUsers_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.entityId = null;
      this.permissionTypeId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getListOfSharedUsers_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getEntityId() {
      return this.entityId;
    }

    public getListOfSharedUsers_args setEntityId(String entityId) {
      this.entityId = entityId;
      return this;
    }

    public void unsetEntityId() {
      this.entityId = null;
    }

    /** Returns true if field entityId is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityId() {
      return this.entityId != null;
    }

    public void setEntityIdIsSet(boolean value) {
      if (!value) {
        this.entityId = null;
      }
    }

    public String getPermissionTypeId() {
      return this.permissionTypeId;
    }

    public getListOfSharedUsers_args setPermissionTypeId(String permissionTypeId) {
      this.permissionTypeId = permissionTypeId;
      return this;
    }

    public void unsetPermissionTypeId() {
      this.permissionTypeId = null;
    }

    /** Returns true if field permissionTypeId is set (has been assigned a value) and false otherwise */
    public boolean isSetPermissionTypeId() {
      return this.permissionTypeId != null;
    }

    public void setPermissionTypeIdIsSet(boolean value) {
      if (!value) {
        this.permissionTypeId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case ENTITY_ID:
        if (value == null) {
          unsetEntityId();
        } else {
          setEntityId((String)value);
        }
        break;

      case PERMISSION_TYPE_ID:
        if (value == null) {
          unsetPermissionTypeId();
        } else {
          setPermissionTypeId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case ENTITY_ID:
        return getEntityId();

      case PERMISSION_TYPE_ID:
        return getPermissionTypeId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case ENTITY_ID:
        return isSetEntityId();
      case PERMISSION_TYPE_ID:
        return isSetPermissionTypeId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getListOfSharedUsers_args)
        return this.equals((getListOfSharedUsers_args)that);
      return false;
    }

    public boolean equals(getListOfSharedUsers_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_entityId = true && this.isSetEntityId();
      boolean that_present_entityId = true && that.isSetEntityId();
      if (this_present_entityId || that_present_entityId) {
        if (!(this_present_entityId && that_present_entityId))
          return false;
        if (!this.entityId.equals(that.entityId))
          return false;
      }

      boolean this_present_permissionTypeId = true && this.isSetPermissionTypeId();
      boolean that_present_permissionTypeId = true && that.isSetPermissionTypeId();
      if (this_present_permissionTypeId || that_present_permissionTypeId) {
        if (!(this_present_permissionTypeId && that_present_permissionTypeId))
          return false;
        if (!this.permissionTypeId.equals(that.permissionTypeId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_entityId = true && (isSetEntityId());
      list.add(present_entityId);
      if (present_entityId)
        list.add(entityId);

      boolean present_permissionTypeId = true && (isSetPermissionTypeId());
      list.add(present_permissionTypeId);
      if (present_permissionTypeId)
        list.add(permissionTypeId);

      return list.hashCode();
    }

    @Override
    public int compareTo(getListOfSharedUsers_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetEntityId()).compareTo(other.isSetEntityId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityId, other.entityId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetPermissionTypeId()).compareTo(other.isSetPermissionTypeId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetPermissionTypeId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.permissionTypeId, other.permissionTypeId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getListOfSharedUsers_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("entityId:");
      if (this.entityId == null) {
        sb.append("null");
      } else {
        sb.append(this.entityId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("permissionTypeId:");
      if (this.permissionTypeId == null) {
        sb.append("null");
      } else {
        sb.append(this.permissionTypeId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (entityId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityId' was not present! Struct: " + toString());
      }
      if (permissionTypeId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'permissionTypeId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getListOfSharedUsers_argsStandardSchemeFactory implements SchemeFactory {
      public getListOfSharedUsers_argsStandardScheme getScheme() {
        return new getListOfSharedUsers_argsStandardScheme();
      }
    }

    private static class getListOfSharedUsers_argsStandardScheme extends StandardScheme<getListOfSharedUsers_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getListOfSharedUsers_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ENTITY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.entityId = iprot.readString();
                struct.setEntityIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // PERMISSION_TYPE_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.permissionTypeId = iprot.readString();
                struct.setPermissionTypeIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getListOfSharedUsers_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.entityId != null) {
          oprot.writeFieldBegin(ENTITY_ID_FIELD_DESC);
          oprot.writeString(struct.entityId);
          oprot.writeFieldEnd();
        }
        if (struct.permissionTypeId != null) {
          oprot.writeFieldBegin(PERMISSION_TYPE_ID_FIELD_DESC);
          oprot.writeString(struct.permissionTypeId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getListOfSharedUsers_argsTupleSchemeFactory implements SchemeFactory {
      public getListOfSharedUsers_argsTupleScheme getScheme() {
        return new getListOfSharedUsers_argsTupleScheme();
      }
    }

    private static class getListOfSharedUsers_argsTupleScheme extends TupleScheme<getListOfSharedUsers_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getListOfSharedUsers_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.entityId);
        oprot.writeString(struct.permissionTypeId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getListOfSharedUsers_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.entityId = iprot.readString();
        struct.setEntityIdIsSet(true);
        struct.permissionTypeId = iprot.readString();
        struct.setPermissionTypeIdIsSet(true);
      }
    }

  }

  public static class getListOfSharedUsers_result implements org.apache.thrift.TBase<getListOfSharedUsers_result, getListOfSharedUsers_result._Fields>, java.io.Serializable, Cloneable, Comparable<getListOfSharedUsers_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getListOfSharedUsers_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getListOfSharedUsers_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getListOfSharedUsers_resultTupleSchemeFactory());
    }

    public List<org.apache.airavata.sharing.registry.models.User> success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.User.class))));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getListOfSharedUsers_result.class, metaDataMap);
    }

    public getListOfSharedUsers_result() {
    }

    public getListOfSharedUsers_result(
      List<org.apache.airavata.sharing.registry.models.User> success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getListOfSharedUsers_result(getListOfSharedUsers_result other) {
      if (other.isSetSuccess()) {
        List<org.apache.airavata.sharing.registry.models.User> __this__success = new ArrayList<org.apache.airavata.sharing.registry.models.User>(other.success.size());
        for (org.apache.airavata.sharing.registry.models.User other_element : other.success) {
          __this__success.add(new org.apache.airavata.sharing.registry.models.User(other_element));
        }
        this.success = __this__success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getListOfSharedUsers_result deepCopy() {
      return new getListOfSharedUsers_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public int getSuccessSize() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<org.apache.airavata.sharing.registry.models.User> getSuccessIterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void addToSuccess(org.apache.airavata.sharing.registry.models.User elem) {
      if (this.success == null) {
        this.success = new ArrayList<org.apache.airavata.sharing.registry.models.User>();
      }
      this.success.add(elem);
    }

    public List<org.apache.airavata.sharing.registry.models.User> getSuccess() {
      return this.success;
    }

    public getListOfSharedUsers_result setSuccess(List<org.apache.airavata.sharing.registry.models.User> success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getListOfSharedUsers_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((List<org.apache.airavata.sharing.registry.models.User>)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getListOfSharedUsers_result)
        return this.equals((getListOfSharedUsers_result)that);
      return false;
    }

    public boolean equals(getListOfSharedUsers_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getListOfSharedUsers_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getListOfSharedUsers_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getListOfSharedUsers_resultStandardSchemeFactory implements SchemeFactory {
      public getListOfSharedUsers_resultStandardScheme getScheme() {
        return new getListOfSharedUsers_resultStandardScheme();
      }
    }

    private static class getListOfSharedUsers_resultStandardScheme extends StandardScheme<getListOfSharedUsers_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getListOfSharedUsers_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list96 = iprot.readListBegin();
                  struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.User>(_list96.size);
                  org.apache.airavata.sharing.registry.models.User _elem97;
                  for (int _i98 = 0; _i98 < _list96.size; ++_i98)
                  {
                    _elem97 = new org.apache.airavata.sharing.registry.models.User();
                    _elem97.read(iprot);
                    struct.success.add(_elem97);
                  }
                  iprot.readListEnd();
                }
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getListOfSharedUsers_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (org.apache.airavata.sharing.registry.models.User _iter99 : struct.success)
            {
              _iter99.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getListOfSharedUsers_resultTupleSchemeFactory implements SchemeFactory {
      public getListOfSharedUsers_resultTupleScheme getScheme() {
        return new getListOfSharedUsers_resultTupleScheme();
      }
    }

    private static class getListOfSharedUsers_resultTupleScheme extends TupleScheme<getListOfSharedUsers_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getListOfSharedUsers_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          {
            oprot.writeI32(struct.success.size());
            for (org.apache.airavata.sharing.registry.models.User _iter100 : struct.success)
            {
              _iter100.write(oprot);
            }
          }
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getListOfSharedUsers_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list101 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.User>(_list101.size);
            org.apache.airavata.sharing.registry.models.User _elem102;
            for (int _i103 = 0; _i103 < _list101.size; ++_i103)
            {
              _elem102 = new org.apache.airavata.sharing.registry.models.User();
              _elem102.read(iprot);
              struct.success.add(_elem102);
            }
          }
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getListOfSharedGroups_args implements org.apache.thrift.TBase<getListOfSharedGroups_args, getListOfSharedGroups_args._Fields>, java.io.Serializable, Cloneable, Comparable<getListOfSharedGroups_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getListOfSharedGroups_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField ENTITY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("entityId", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField PERMISSION_TYPE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("permissionTypeId", org.apache.thrift.protocol.TType.STRING, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getListOfSharedGroups_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getListOfSharedGroups_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String entityId; // required
    public String permissionTypeId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      ENTITY_ID((short)2, "entityId"),
      PERMISSION_TYPE_ID((short)3, "permissionTypeId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // ENTITY_ID
            return ENTITY_ID;
          case 3: // PERMISSION_TYPE_ID
            return PERMISSION_TYPE_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.ENTITY_ID, new org.apache.thrift.meta_data.FieldMetaData("entityId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.PERMISSION_TYPE_ID, new org.apache.thrift.meta_data.FieldMetaData("permissionTypeId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getListOfSharedGroups_args.class, metaDataMap);
    }

    public getListOfSharedGroups_args() {
    }

    public getListOfSharedGroups_args(
      String domainId,
      String entityId,
      String permissionTypeId)
    {
      this();
      this.domainId = domainId;
      this.entityId = entityId;
      this.permissionTypeId = permissionTypeId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getListOfSharedGroups_args(getListOfSharedGroups_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetEntityId()) {
        this.entityId = other.entityId;
      }
      if (other.isSetPermissionTypeId()) {
        this.permissionTypeId = other.permissionTypeId;
      }
    }

    public getListOfSharedGroups_args deepCopy() {
      return new getListOfSharedGroups_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.entityId = null;
      this.permissionTypeId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getListOfSharedGroups_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getEntityId() {
      return this.entityId;
    }

    public getListOfSharedGroups_args setEntityId(String entityId) {
      this.entityId = entityId;
      return this;
    }

    public void unsetEntityId() {
      this.entityId = null;
    }

    /** Returns true if field entityId is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityId() {
      return this.entityId != null;
    }

    public void setEntityIdIsSet(boolean value) {
      if (!value) {
        this.entityId = null;
      }
    }

    public String getPermissionTypeId() {
      return this.permissionTypeId;
    }

    public getListOfSharedGroups_args setPermissionTypeId(String permissionTypeId) {
      this.permissionTypeId = permissionTypeId;
      return this;
    }

    public void unsetPermissionTypeId() {
      this.permissionTypeId = null;
    }

    /** Returns true if field permissionTypeId is set (has been assigned a value) and false otherwise */
    public boolean isSetPermissionTypeId() {
      return this.permissionTypeId != null;
    }

    public void setPermissionTypeIdIsSet(boolean value) {
      if (!value) {
        this.permissionTypeId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case ENTITY_ID:
        if (value == null) {
          unsetEntityId();
        } else {
          setEntityId((String)value);
        }
        break;

      case PERMISSION_TYPE_ID:
        if (value == null) {
          unsetPermissionTypeId();
        } else {
          setPermissionTypeId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case ENTITY_ID:
        return getEntityId();

      case PERMISSION_TYPE_ID:
        return getPermissionTypeId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case ENTITY_ID:
        return isSetEntityId();
      case PERMISSION_TYPE_ID:
        return isSetPermissionTypeId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getListOfSharedGroups_args)
        return this.equals((getListOfSharedGroups_args)that);
      return false;
    }

    public boolean equals(getListOfSharedGroups_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_entityId = true && this.isSetEntityId();
      boolean that_present_entityId = true && that.isSetEntityId();
      if (this_present_entityId || that_present_entityId) {
        if (!(this_present_entityId && that_present_entityId))
          return false;
        if (!this.entityId.equals(that.entityId))
          return false;
      }

      boolean this_present_permissionTypeId = true && this.isSetPermissionTypeId();
      boolean that_present_permissionTypeId = true && that.isSetPermissionTypeId();
      if (this_present_permissionTypeId || that_present_permissionTypeId) {
        if (!(this_present_permissionTypeId && that_present_permissionTypeId))
          return false;
        if (!this.permissionTypeId.equals(that.permissionTypeId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_entityId = true && (isSetEntityId());
      list.add(present_entityId);
      if (present_entityId)
        list.add(entityId);

      boolean present_permissionTypeId = true && (isSetPermissionTypeId());
      list.add(present_permissionTypeId);
      if (present_permissionTypeId)
        list.add(permissionTypeId);

      return list.hashCode();
    }

    @Override
    public int compareTo(getListOfSharedGroups_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetEntityId()).compareTo(other.isSetEntityId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityId, other.entityId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetPermissionTypeId()).compareTo(other.isSetPermissionTypeId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetPermissionTypeId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.permissionTypeId, other.permissionTypeId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getListOfSharedGroups_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("entityId:");
      if (this.entityId == null) {
        sb.append("null");
      } else {
        sb.append(this.entityId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("permissionTypeId:");
      if (this.permissionTypeId == null) {
        sb.append("null");
      } else {
        sb.append(this.permissionTypeId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (entityId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityId' was not present! Struct: " + toString());
      }
      if (permissionTypeId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'permissionTypeId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getListOfSharedGroups_argsStandardSchemeFactory implements SchemeFactory {
      public getListOfSharedGroups_argsStandardScheme getScheme() {
        return new getListOfSharedGroups_argsStandardScheme();
      }
    }

    private static class getListOfSharedGroups_argsStandardScheme extends StandardScheme<getListOfSharedGroups_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getListOfSharedGroups_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ENTITY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.entityId = iprot.readString();
                struct.setEntityIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // PERMISSION_TYPE_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.permissionTypeId = iprot.readString();
                struct.setPermissionTypeIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getListOfSharedGroups_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.entityId != null) {
          oprot.writeFieldBegin(ENTITY_ID_FIELD_DESC);
          oprot.writeString(struct.entityId);
          oprot.writeFieldEnd();
        }
        if (struct.permissionTypeId != null) {
          oprot.writeFieldBegin(PERMISSION_TYPE_ID_FIELD_DESC);
          oprot.writeString(struct.permissionTypeId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getListOfSharedGroups_argsTupleSchemeFactory implements SchemeFactory {
      public getListOfSharedGroups_argsTupleScheme getScheme() {
        return new getListOfSharedGroups_argsTupleScheme();
      }
    }

    private static class getListOfSharedGroups_argsTupleScheme extends TupleScheme<getListOfSharedGroups_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getListOfSharedGroups_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.entityId);
        oprot.writeString(struct.permissionTypeId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getListOfSharedGroups_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.entityId = iprot.readString();
        struct.setEntityIdIsSet(true);
        struct.permissionTypeId = iprot.readString();
        struct.setPermissionTypeIdIsSet(true);
      }
    }

  }

  public static class getListOfSharedGroups_result implements org.apache.thrift.TBase<getListOfSharedGroups_result, getListOfSharedGroups_result._Fields>, java.io.Serializable, Cloneable, Comparable<getListOfSharedGroups_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getListOfSharedGroups_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getListOfSharedGroups_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getListOfSharedGroups_resultTupleSchemeFactory());
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.UserGroup.class))));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getListOfSharedGroups_result.class, metaDataMap);
    }

    public getListOfSharedGroups_result() {
    }

    public getListOfSharedGroups_result(
      List<org.apache.airavata.sharing.registry.models.UserGroup> success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getListOfSharedGroups_result(getListOfSharedGroups_result other) {
      if (other.isSetSuccess()) {
        List<org.apache.airavata.sharing.registry.models.UserGroup> __this__success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>(other.success.size());
        for (org.apache.airavata.sharing.registry.models.UserGroup other_element : other.success) {
          __this__success.add(new org.apache.airavata.sharing.registry.models.UserGroup(other_element));
        }
        this.success = __this__success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getListOfSharedGroups_result deepCopy() {
      return new getListOfSharedGroups_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public int getSuccessSize() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<org.apache.airavata.sharing.registry.models.UserGroup> getSuccessIterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void addToSuccess(org.apache.airavata.sharing.registry.models.UserGroup elem) {
      if (this.success == null) {
        this.success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>();
      }
      this.success.add(elem);
    }

    public List<org.apache.airavata.sharing.registry.models.UserGroup> getSuccess() {
      return this.success;
    }

    public getListOfSharedGroups_result setSuccess(List<org.apache.airavata.sharing.registry.models.UserGroup> success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getListOfSharedGroups_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((List<org.apache.airavata.sharing.registry.models.UserGroup>)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getListOfSharedGroups_result)
        return this.equals((getListOfSharedGroups_result)that);
      return false;
    }

    public boolean equals(getListOfSharedGroups_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getListOfSharedGroups_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getListOfSharedGroups_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getListOfSharedGroups_resultStandardSchemeFactory implements SchemeFactory {
      public getListOfSharedGroups_resultStandardScheme getScheme() {
        return new getListOfSharedGroups_resultStandardScheme();
      }
    }

    private static class getListOfSharedGroups_resultStandardScheme extends StandardScheme<getListOfSharedGroups_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getListOfSharedGroups_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list104 = iprot.readListBegin();
                  struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>(_list104.size);
                  org.apache.airavata.sharing.registry.models.UserGroup _elem105;
                  for (int _i106 = 0; _i106 < _list104.size; ++_i106)
                  {
                    _elem105 = new org.apache.airavata.sharing.registry.models.UserGroup();
                    _elem105.read(iprot);
                    struct.success.add(_elem105);
                  }
                  iprot.readListEnd();
                }
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getListOfSharedGroups_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (org.apache.airavata.sharing.registry.models.UserGroup _iter107 : struct.success)
            {
              _iter107.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getListOfSharedGroups_resultTupleSchemeFactory implements SchemeFactory {
      public getListOfSharedGroups_resultTupleScheme getScheme() {
        return new getListOfSharedGroups_resultTupleScheme();
      }
    }

    private static class getListOfSharedGroups_resultTupleScheme extends TupleScheme<getListOfSharedGroups_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getListOfSharedGroups_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          {
            oprot.writeI32(struct.success.size());
            for (org.apache.airavata.sharing.registry.models.UserGroup _iter108 : struct.success)
            {
              _iter108.write(oprot);
            }
          }
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getListOfSharedGroups_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list109 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.UserGroup>(_list109.size);
            org.apache.airavata.sharing.registry.models.UserGroup _elem110;
            for (int _i111 = 0; _i111 < _list109.size; ++_i111)
            {
              _elem110 = new org.apache.airavata.sharing.registry.models.UserGroup();
              _elem110.read(iprot);
              struct.success.add(_elem110);
            }
          }
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class createPermissionType_args implements org.apache.thrift.TBase<createPermissionType_args, createPermissionType_args._Fields>, java.io.Serializable, Cloneable, Comparable<createPermissionType_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createPermissionType_args");

    private static final org.apache.thrift.protocol.TField PERMISSION_TYPE_FIELD_DESC = new org.apache.thrift.protocol.TField("permissionType", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new createPermissionType_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new createPermissionType_argsTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.PermissionType permissionType; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      PERMISSION_TYPE((short)1, "permissionType");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // PERMISSION_TYPE
            return PERMISSION_TYPE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.PERMISSION_TYPE, new org.apache.thrift.meta_data.FieldMetaData("permissionType", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.PermissionType.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createPermissionType_args.class, metaDataMap);
    }

    public createPermissionType_args() {
    }

    public createPermissionType_args(
      org.apache.airavata.sharing.registry.models.PermissionType permissionType)
    {
      this();
      this.permissionType = permissionType;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public createPermissionType_args(createPermissionType_args other) {
      if (other.isSetPermissionType()) {
        this.permissionType = new org.apache.airavata.sharing.registry.models.PermissionType(other.permissionType);
      }
    }

    public createPermissionType_args deepCopy() {
      return new createPermissionType_args(this);
    }

    @Override
    public void clear() {
      this.permissionType = null;
    }

    public org.apache.airavata.sharing.registry.models.PermissionType getPermissionType() {
      return this.permissionType;
    }

    public createPermissionType_args setPermissionType(org.apache.airavata.sharing.registry.models.PermissionType permissionType) {
      this.permissionType = permissionType;
      return this;
    }

    public void unsetPermissionType() {
      this.permissionType = null;
    }

    /** Returns true if field permissionType is set (has been assigned a value) and false otherwise */
    public boolean isSetPermissionType() {
      return this.permissionType != null;
    }

    public void setPermissionTypeIsSet(boolean value) {
      if (!value) {
        this.permissionType = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case PERMISSION_TYPE:
        if (value == null) {
          unsetPermissionType();
        } else {
          setPermissionType((org.apache.airavata.sharing.registry.models.PermissionType)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case PERMISSION_TYPE:
        return getPermissionType();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case PERMISSION_TYPE:
        return isSetPermissionType();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof createPermissionType_args)
        return this.equals((createPermissionType_args)that);
      return false;
    }

    public boolean equals(createPermissionType_args that) {
      if (that == null)
        return false;

      boolean this_present_permissionType = true && this.isSetPermissionType();
      boolean that_present_permissionType = true && that.isSetPermissionType();
      if (this_present_permissionType || that_present_permissionType) {
        if (!(this_present_permissionType && that_present_permissionType))
          return false;
        if (!this.permissionType.equals(that.permissionType))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_permissionType = true && (isSetPermissionType());
      list.add(present_permissionType);
      if (present_permissionType)
        list.add(permissionType);

      return list.hashCode();
    }

    @Override
    public int compareTo(createPermissionType_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetPermissionType()).compareTo(other.isSetPermissionType());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetPermissionType()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.permissionType, other.permissionType);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("createPermissionType_args(");
      boolean first = true;

      sb.append("permissionType:");
      if (this.permissionType == null) {
        sb.append("null");
      } else {
        sb.append(this.permissionType);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (permissionType == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'permissionType' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
      if (permissionType != null) {
        permissionType.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class createPermissionType_argsStandardSchemeFactory implements SchemeFactory {
      public createPermissionType_argsStandardScheme getScheme() {
        return new createPermissionType_argsStandardScheme();
      }
    }

    private static class createPermissionType_argsStandardScheme extends StandardScheme<createPermissionType_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, createPermissionType_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // PERMISSION_TYPE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.permissionType = new org.apache.airavata.sharing.registry.models.PermissionType();
                struct.permissionType.read(iprot);
                struct.setPermissionTypeIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, createPermissionType_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.permissionType != null) {
          oprot.writeFieldBegin(PERMISSION_TYPE_FIELD_DESC);
          struct.permissionType.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class createPermissionType_argsTupleSchemeFactory implements SchemeFactory {
      public createPermissionType_argsTupleScheme getScheme() {
        return new createPermissionType_argsTupleScheme();
      }
    }

    private static class createPermissionType_argsTupleScheme extends TupleScheme<createPermissionType_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, createPermissionType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        struct.permissionType.write(oprot);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, createPermissionType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.permissionType = new org.apache.airavata.sharing.registry.models.PermissionType();
        struct.permissionType.read(iprot);
        struct.setPermissionTypeIsSet(true);
      }
    }

  }

  public static class createPermissionType_result implements org.apache.thrift.TBase<createPermissionType_result, createPermissionType_result._Fields>, java.io.Serializable, Cloneable, Comparable<createPermissionType_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createPermissionType_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRING, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);
    private static final org.apache.thrift.protocol.TField DEE_FIELD_DESC = new org.apache.thrift.protocol.TField("dee", org.apache.thrift.protocol.TType.STRUCT, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new createPermissionType_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new createPermissionType_resultTupleSchemeFactory());
    }

    public String success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required
    public org.apache.airavata.sharing.registry.models.DuplicateEntryException dee; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre"),
      DEE((short)2, "dee");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          case 2: // DEE
            return DEE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      tmpMap.put(_Fields.DEE, new org.apache.thrift.meta_data.FieldMetaData("dee", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createPermissionType_result.class, metaDataMap);
    }

    public createPermissionType_result() {
    }

    public createPermissionType_result(
      String success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre,
      org.apache.airavata.sharing.registry.models.DuplicateEntryException dee)
    {
      this();
      this.success = success;
      this.sre = sre;
      this.dee = dee;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public createPermissionType_result(createPermissionType_result other) {
      if (other.isSetSuccess()) {
        this.success = other.success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
      if (other.isSetDee()) {
        this.dee = new org.apache.airavata.sharing.registry.models.DuplicateEntryException(other.dee);
      }
    }

    public createPermissionType_result deepCopy() {
      return new createPermissionType_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
      this.dee = null;
    }

    public String getSuccess() {
      return this.success;
    }

    public createPermissionType_result setSuccess(String success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public createPermissionType_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.DuplicateEntryException getDee() {
      return this.dee;
    }

    public createPermissionType_result setDee(org.apache.airavata.sharing.registry.models.DuplicateEntryException dee) {
      this.dee = dee;
      return this;
    }

    public void unsetDee() {
      this.dee = null;
    }

    /** Returns true if field dee is set (has been assigned a value) and false otherwise */
    public boolean isSetDee() {
      return this.dee != null;
    }

    public void setDeeIsSet(boolean value) {
      if (!value) {
        this.dee = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((String)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      case DEE:
        if (value == null) {
          unsetDee();
        } else {
          setDee((org.apache.airavata.sharing.registry.models.DuplicateEntryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      case DEE:
        return getDee();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      case DEE:
        return isSetDee();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof createPermissionType_result)
        return this.equals((createPermissionType_result)that);
      return false;
    }

    public boolean equals(createPermissionType_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      boolean this_present_dee = true && this.isSetDee();
      boolean that_present_dee = true && that.isSetDee();
      if (this_present_dee || that_present_dee) {
        if (!(this_present_dee && that_present_dee))
          return false;
        if (!this.dee.equals(that.dee))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      boolean present_dee = true && (isSetDee());
      list.add(present_dee);
      if (present_dee)
        list.add(dee);

      return list.hashCode();
    }

    @Override
    public int compareTo(createPermissionType_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetDee()).compareTo(other.isSetDee());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDee()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.dee, other.dee);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("createPermissionType_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("dee:");
      if (this.dee == null) {
        sb.append("null");
      } else {
        sb.append(this.dee);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class createPermissionType_resultStandardSchemeFactory implements SchemeFactory {
      public createPermissionType_resultStandardScheme getScheme() {
        return new createPermissionType_resultStandardScheme();
      }
    }

    private static class createPermissionType_resultStandardScheme extends StandardScheme<createPermissionType_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, createPermissionType_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.success = iprot.readString();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // DEE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.dee = new org.apache.airavata.sharing.registry.models.DuplicateEntryException();
                struct.dee.read(iprot);
                struct.setDeeIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, createPermissionType_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeString(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.dee != null) {
          oprot.writeFieldBegin(DEE_FIELD_DESC);
          struct.dee.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class createPermissionType_resultTupleSchemeFactory implements SchemeFactory {
      public createPermissionType_resultTupleScheme getScheme() {
        return new createPermissionType_resultTupleScheme();
      }
    }

    private static class createPermissionType_resultTupleScheme extends TupleScheme<createPermissionType_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, createPermissionType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        if (struct.isSetDee()) {
          optionals.set(2);
        }
        oprot.writeBitSet(optionals, 3);
        if (struct.isSetSuccess()) {
          oprot.writeString(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
        if (struct.isSetDee()) {
          struct.dee.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, createPermissionType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(3);
        if (incoming.get(0)) {
          struct.success = iprot.readString();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
        if (incoming.get(2)) {
          struct.dee = new org.apache.airavata.sharing.registry.models.DuplicateEntryException();
          struct.dee.read(iprot);
          struct.setDeeIsSet(true);
        }
      }
    }

  }

  public static class updatePermissionType_args implements org.apache.thrift.TBase<updatePermissionType_args, updatePermissionType_args._Fields>, java.io.Serializable, Cloneable, Comparable<updatePermissionType_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updatePermissionType_args");

    private static final org.apache.thrift.protocol.TField PERMISSION_TYPE_FIELD_DESC = new org.apache.thrift.protocol.TField("permissionType", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updatePermissionType_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updatePermissionType_argsTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.PermissionType permissionType; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      PERMISSION_TYPE((short)1, "permissionType");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // PERMISSION_TYPE
            return PERMISSION_TYPE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.PERMISSION_TYPE, new org.apache.thrift.meta_data.FieldMetaData("permissionType", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.PermissionType.class)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updatePermissionType_args.class, metaDataMap);
    }

    public updatePermissionType_args() {
    }

    public updatePermissionType_args(
      org.apache.airavata.sharing.registry.models.PermissionType permissionType)
    {
      this();
      this.permissionType = permissionType;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updatePermissionType_args(updatePermissionType_args other) {
      if (other.isSetPermissionType()) {
        this.permissionType = new org.apache.airavata.sharing.registry.models.PermissionType(other.permissionType);
      }
    }

    public updatePermissionType_args deepCopy() {
      return new updatePermissionType_args(this);
    }

    @Override
    public void clear() {
      this.permissionType = null;
    }

    public org.apache.airavata.sharing.registry.models.PermissionType getPermissionType() {
      return this.permissionType;
    }

    public updatePermissionType_args setPermissionType(org.apache.airavata.sharing.registry.models.PermissionType permissionType) {
      this.permissionType = permissionType;
      return this;
    }

    public void unsetPermissionType() {
      this.permissionType = null;
    }

    /** Returns true if field permissionType is set (has been assigned a value) and false otherwise */
    public boolean isSetPermissionType() {
      return this.permissionType != null;
    }

    public void setPermissionTypeIsSet(boolean value) {
      if (!value) {
        this.permissionType = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case PERMISSION_TYPE:
        if (value == null) {
          unsetPermissionType();
        } else {
          setPermissionType((org.apache.airavata.sharing.registry.models.PermissionType)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case PERMISSION_TYPE:
        return getPermissionType();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case PERMISSION_TYPE:
        return isSetPermissionType();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updatePermissionType_args)
        return this.equals((updatePermissionType_args)that);
      return false;
    }

    public boolean equals(updatePermissionType_args that) {
      if (that == null)
        return false;

      boolean this_present_permissionType = true && this.isSetPermissionType();
      boolean that_present_permissionType = true && that.isSetPermissionType();
      if (this_present_permissionType || that_present_permissionType) {
        if (!(this_present_permissionType && that_present_permissionType))
          return false;
        if (!this.permissionType.equals(that.permissionType))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_permissionType = true && (isSetPermissionType());
      list.add(present_permissionType);
      if (present_permissionType)
        list.add(permissionType);

      return list.hashCode();
    }

    @Override
    public int compareTo(updatePermissionType_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetPermissionType()).compareTo(other.isSetPermissionType());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetPermissionType()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.permissionType, other.permissionType);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updatePermissionType_args(");
      boolean first = true;

      sb.append("permissionType:");
      if (this.permissionType == null) {
        sb.append("null");
      } else {
        sb.append(this.permissionType);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (permissionType == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'permissionType' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
      if (permissionType != null) {
        permissionType.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updatePermissionType_argsStandardSchemeFactory implements SchemeFactory {
      public updatePermissionType_argsStandardScheme getScheme() {
        return new updatePermissionType_argsStandardScheme();
      }
    }

    private static class updatePermissionType_argsStandardScheme extends StandardScheme<updatePermissionType_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updatePermissionType_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // PERMISSION_TYPE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.permissionType = new org.apache.airavata.sharing.registry.models.PermissionType();
                struct.permissionType.read(iprot);
                struct.setPermissionTypeIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updatePermissionType_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.permissionType != null) {
          oprot.writeFieldBegin(PERMISSION_TYPE_FIELD_DESC);
          struct.permissionType.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updatePermissionType_argsTupleSchemeFactory implements SchemeFactory {
      public updatePermissionType_argsTupleScheme getScheme() {
        return new updatePermissionType_argsTupleScheme();
      }
    }

    private static class updatePermissionType_argsTupleScheme extends TupleScheme<updatePermissionType_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updatePermissionType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        struct.permissionType.write(oprot);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updatePermissionType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.permissionType = new org.apache.airavata.sharing.registry.models.PermissionType();
        struct.permissionType.read(iprot);
        struct.setPermissionTypeIsSet(true);
      }
    }

  }

  public static class updatePermissionType_result implements org.apache.thrift.TBase<updatePermissionType_result, updatePermissionType_result._Fields>, java.io.Serializable, Cloneable, Comparable<updatePermissionType_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("updatePermissionType_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new updatePermissionType_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new updatePermissionType_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(updatePermissionType_result.class, metaDataMap);
    }

    public updatePermissionType_result() {
    }

    public updatePermissionType_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public updatePermissionType_result(updatePermissionType_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public updatePermissionType_result deepCopy() {
      return new updatePermissionType_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public updatePermissionType_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public updatePermissionType_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof updatePermissionType_result)
        return this.equals((updatePermissionType_result)that);
      return false;
    }

    public boolean equals(updatePermissionType_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(updatePermissionType_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("updatePermissionType_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class updatePermissionType_resultStandardSchemeFactory implements SchemeFactory {
      public updatePermissionType_resultStandardScheme getScheme() {
        return new updatePermissionType_resultStandardScheme();
      }
    }

    private static class updatePermissionType_resultStandardScheme extends StandardScheme<updatePermissionType_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, updatePermissionType_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, updatePermissionType_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class updatePermissionType_resultTupleSchemeFactory implements SchemeFactory {
      public updatePermissionType_resultTupleScheme getScheme() {
        return new updatePermissionType_resultTupleScheme();
      }
    }

    private static class updatePermissionType_resultTupleScheme extends TupleScheme<updatePermissionType_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, updatePermissionType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, updatePermissionType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class isPermissionExists_args implements org.apache.thrift.TBase<isPermissionExists_args, isPermissionExists_args._Fields>, java.io.Serializable, Cloneable, Comparable<isPermissionExists_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("isPermissionExists_args");

    private static final org.apache.thrift.protocol.TField DIMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("dimainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField PERMISSION_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("permissionId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new isPermissionExists_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new isPermissionExists_argsTupleSchemeFactory());
    }

    public String dimainId; // required
    public String permissionId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DIMAIN_ID((short)1, "dimainId"),
      PERMISSION_ID((short)2, "permissionId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DIMAIN_ID
            return DIMAIN_ID;
          case 2: // PERMISSION_ID
            return PERMISSION_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DIMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("dimainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.PERMISSION_ID, new org.apache.thrift.meta_data.FieldMetaData("permissionId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(isPermissionExists_args.class, metaDataMap);
    }

    public isPermissionExists_args() {
    }

    public isPermissionExists_args(
      String dimainId,
      String permissionId)
    {
      this();
      this.dimainId = dimainId;
      this.permissionId = permissionId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public isPermissionExists_args(isPermissionExists_args other) {
      if (other.isSetDimainId()) {
        this.dimainId = other.dimainId;
      }
      if (other.isSetPermissionId()) {
        this.permissionId = other.permissionId;
      }
    }

    public isPermissionExists_args deepCopy() {
      return new isPermissionExists_args(this);
    }

    @Override
    public void clear() {
      this.dimainId = null;
      this.permissionId = null;
    }

    public String getDimainId() {
      return this.dimainId;
    }

    public isPermissionExists_args setDimainId(String dimainId) {
      this.dimainId = dimainId;
      return this;
    }

    public void unsetDimainId() {
      this.dimainId = null;
    }

    /** Returns true if field dimainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDimainId() {
      return this.dimainId != null;
    }

    public void setDimainIdIsSet(boolean value) {
      if (!value) {
        this.dimainId = null;
      }
    }

    public String getPermissionId() {
      return this.permissionId;
    }

    public isPermissionExists_args setPermissionId(String permissionId) {
      this.permissionId = permissionId;
      return this;
    }

    public void unsetPermissionId() {
      this.permissionId = null;
    }

    /** Returns true if field permissionId is set (has been assigned a value) and false otherwise */
    public boolean isSetPermissionId() {
      return this.permissionId != null;
    }

    public void setPermissionIdIsSet(boolean value) {
      if (!value) {
        this.permissionId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DIMAIN_ID:
        if (value == null) {
          unsetDimainId();
        } else {
          setDimainId((String)value);
        }
        break;

      case PERMISSION_ID:
        if (value == null) {
          unsetPermissionId();
        } else {
          setPermissionId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DIMAIN_ID:
        return getDimainId();

      case PERMISSION_ID:
        return getPermissionId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DIMAIN_ID:
        return isSetDimainId();
      case PERMISSION_ID:
        return isSetPermissionId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof isPermissionExists_args)
        return this.equals((isPermissionExists_args)that);
      return false;
    }

    public boolean equals(isPermissionExists_args that) {
      if (that == null)
        return false;

      boolean this_present_dimainId = true && this.isSetDimainId();
      boolean that_present_dimainId = true && that.isSetDimainId();
      if (this_present_dimainId || that_present_dimainId) {
        if (!(this_present_dimainId && that_present_dimainId))
          return false;
        if (!this.dimainId.equals(that.dimainId))
          return false;
      }

      boolean this_present_permissionId = true && this.isSetPermissionId();
      boolean that_present_permissionId = true && that.isSetPermissionId();
      if (this_present_permissionId || that_present_permissionId) {
        if (!(this_present_permissionId && that_present_permissionId))
          return false;
        if (!this.permissionId.equals(that.permissionId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_dimainId = true && (isSetDimainId());
      list.add(present_dimainId);
      if (present_dimainId)
        list.add(dimainId);

      boolean present_permissionId = true && (isSetPermissionId());
      list.add(present_permissionId);
      if (present_permissionId)
        list.add(permissionId);

      return list.hashCode();
    }

    @Override
    public int compareTo(isPermissionExists_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDimainId()).compareTo(other.isSetDimainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDimainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.dimainId, other.dimainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetPermissionId()).compareTo(other.isSetPermissionId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetPermissionId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.permissionId, other.permissionId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("isPermissionExists_args(");
      boolean first = true;

      sb.append("dimainId:");
      if (this.dimainId == null) {
        sb.append("null");
      } else {
        sb.append(this.dimainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("permissionId:");
      if (this.permissionId == null) {
        sb.append("null");
      } else {
        sb.append(this.permissionId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (dimainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'dimainId' was not present! Struct: " + toString());
      }
      if (permissionId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'permissionId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class isPermissionExists_argsStandardSchemeFactory implements SchemeFactory {
      public isPermissionExists_argsStandardScheme getScheme() {
        return new isPermissionExists_argsStandardScheme();
      }
    }

    private static class isPermissionExists_argsStandardScheme extends StandardScheme<isPermissionExists_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, isPermissionExists_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DIMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.dimainId = iprot.readString();
                struct.setDimainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // PERMISSION_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.permissionId = iprot.readString();
                struct.setPermissionIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, isPermissionExists_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.dimainId != null) {
          oprot.writeFieldBegin(DIMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.dimainId);
          oprot.writeFieldEnd();
        }
        if (struct.permissionId != null) {
          oprot.writeFieldBegin(PERMISSION_ID_FIELD_DESC);
          oprot.writeString(struct.permissionId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class isPermissionExists_argsTupleSchemeFactory implements SchemeFactory {
      public isPermissionExists_argsTupleScheme getScheme() {
        return new isPermissionExists_argsTupleScheme();
      }
    }

    private static class isPermissionExists_argsTupleScheme extends TupleScheme<isPermissionExists_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, isPermissionExists_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.dimainId);
        oprot.writeString(struct.permissionId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, isPermissionExists_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.dimainId = iprot.readString();
        struct.setDimainIdIsSet(true);
        struct.permissionId = iprot.readString();
        struct.setPermissionIdIsSet(true);
      }
    }

  }

  public static class isPermissionExists_result implements org.apache.thrift.TBase<isPermissionExists_result, isPermissionExists_result._Fields>, java.io.Serializable, Cloneable, Comparable<isPermissionExists_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("isPermissionExists_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new isPermissionExists_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new isPermissionExists_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(isPermissionExists_result.class, metaDataMap);
    }

    public isPermissionExists_result() {
    }

    public isPermissionExists_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public isPermissionExists_result(isPermissionExists_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public isPermissionExists_result deepCopy() {
      return new isPermissionExists_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public isPermissionExists_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public isPermissionExists_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof isPermissionExists_result)
        return this.equals((isPermissionExists_result)that);
      return false;
    }

    public boolean equals(isPermissionExists_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(isPermissionExists_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("isPermissionExists_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class isPermissionExists_resultStandardSchemeFactory implements SchemeFactory {
      public isPermissionExists_resultStandardScheme getScheme() {
        return new isPermissionExists_resultStandardScheme();
      }
    }

    private static class isPermissionExists_resultStandardScheme extends StandardScheme<isPermissionExists_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, isPermissionExists_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, isPermissionExists_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class isPermissionExists_resultTupleSchemeFactory implements SchemeFactory {
      public isPermissionExists_resultTupleScheme getScheme() {
        return new isPermissionExists_resultTupleScheme();
      }
    }

    private static class isPermissionExists_resultTupleScheme extends TupleScheme<isPermissionExists_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, isPermissionExists_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, isPermissionExists_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class deletePermissionType_args implements org.apache.thrift.TBase<deletePermissionType_args, deletePermissionType_args._Fields>, java.io.Serializable, Cloneable, Comparable<deletePermissionType_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deletePermissionType_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField PERMISSION_TYPE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("permissionTypeId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deletePermissionType_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deletePermissionType_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String permissionTypeId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      PERMISSION_TYPE_ID((short)2, "permissionTypeId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // PERMISSION_TYPE_ID
            return PERMISSION_TYPE_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.PERMISSION_TYPE_ID, new org.apache.thrift.meta_data.FieldMetaData("permissionTypeId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deletePermissionType_args.class, metaDataMap);
    }

    public deletePermissionType_args() {
    }

    public deletePermissionType_args(
      String domainId,
      String permissionTypeId)
    {
      this();
      this.domainId = domainId;
      this.permissionTypeId = permissionTypeId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deletePermissionType_args(deletePermissionType_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetPermissionTypeId()) {
        this.permissionTypeId = other.permissionTypeId;
      }
    }

    public deletePermissionType_args deepCopy() {
      return new deletePermissionType_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.permissionTypeId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public deletePermissionType_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getPermissionTypeId() {
      return this.permissionTypeId;
    }

    public deletePermissionType_args setPermissionTypeId(String permissionTypeId) {
      this.permissionTypeId = permissionTypeId;
      return this;
    }

    public void unsetPermissionTypeId() {
      this.permissionTypeId = null;
    }

    /** Returns true if field permissionTypeId is set (has been assigned a value) and false otherwise */
    public boolean isSetPermissionTypeId() {
      return this.permissionTypeId != null;
    }

    public void setPermissionTypeIdIsSet(boolean value) {
      if (!value) {
        this.permissionTypeId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case PERMISSION_TYPE_ID:
        if (value == null) {
          unsetPermissionTypeId();
        } else {
          setPermissionTypeId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case PERMISSION_TYPE_ID:
        return getPermissionTypeId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case PERMISSION_TYPE_ID:
        return isSetPermissionTypeId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deletePermissionType_args)
        return this.equals((deletePermissionType_args)that);
      return false;
    }

    public boolean equals(deletePermissionType_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_permissionTypeId = true && this.isSetPermissionTypeId();
      boolean that_present_permissionTypeId = true && that.isSetPermissionTypeId();
      if (this_present_permissionTypeId || that_present_permissionTypeId) {
        if (!(this_present_permissionTypeId && that_present_permissionTypeId))
          return false;
        if (!this.permissionTypeId.equals(that.permissionTypeId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_permissionTypeId = true && (isSetPermissionTypeId());
      list.add(present_permissionTypeId);
      if (present_permissionTypeId)
        list.add(permissionTypeId);

      return list.hashCode();
    }

    @Override
    public int compareTo(deletePermissionType_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetPermissionTypeId()).compareTo(other.isSetPermissionTypeId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetPermissionTypeId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.permissionTypeId, other.permissionTypeId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deletePermissionType_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("permissionTypeId:");
      if (this.permissionTypeId == null) {
        sb.append("null");
      } else {
        sb.append(this.permissionTypeId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (permissionTypeId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'permissionTypeId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deletePermissionType_argsStandardSchemeFactory implements SchemeFactory {
      public deletePermissionType_argsStandardScheme getScheme() {
        return new deletePermissionType_argsStandardScheme();
      }
    }

    private static class deletePermissionType_argsStandardScheme extends StandardScheme<deletePermissionType_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deletePermissionType_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // PERMISSION_TYPE_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.permissionTypeId = iprot.readString();
                struct.setPermissionTypeIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deletePermissionType_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.permissionTypeId != null) {
          oprot.writeFieldBegin(PERMISSION_TYPE_ID_FIELD_DESC);
          oprot.writeString(struct.permissionTypeId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deletePermissionType_argsTupleSchemeFactory implements SchemeFactory {
      public deletePermissionType_argsTupleScheme getScheme() {
        return new deletePermissionType_argsTupleScheme();
      }
    }

    private static class deletePermissionType_argsTupleScheme extends TupleScheme<deletePermissionType_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deletePermissionType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.permissionTypeId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deletePermissionType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.permissionTypeId = iprot.readString();
        struct.setPermissionTypeIdIsSet(true);
      }
    }

  }

  public static class deletePermissionType_result implements org.apache.thrift.TBase<deletePermissionType_result, deletePermissionType_result._Fields>, java.io.Serializable, Cloneable, Comparable<deletePermissionType_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deletePermissionType_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new deletePermissionType_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new deletePermissionType_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deletePermissionType_result.class, metaDataMap);
    }

    public deletePermissionType_result() {
    }

    public deletePermissionType_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public deletePermissionType_result(deletePermissionType_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public deletePermissionType_result deepCopy() {
      return new deletePermissionType_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public deletePermissionType_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public deletePermissionType_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof deletePermissionType_result)
        return this.equals((deletePermissionType_result)that);
      return false;
    }

    public boolean equals(deletePermissionType_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(deletePermissionType_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("deletePermissionType_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class deletePermissionType_resultStandardSchemeFactory implements SchemeFactory {
      public deletePermissionType_resultStandardScheme getScheme() {
        return new deletePermissionType_resultStandardScheme();
      }
    }

    private static class deletePermissionType_resultStandardScheme extends StandardScheme<deletePermissionType_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, deletePermissionType_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, deletePermissionType_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class deletePermissionType_resultTupleSchemeFactory implements SchemeFactory {
      public deletePermissionType_resultTupleScheme getScheme() {
        return new deletePermissionType_resultTupleScheme();
      }
    }

    private static class deletePermissionType_resultTupleScheme extends TupleScheme<deletePermissionType_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, deletePermissionType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, deletePermissionType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getPermissionType_args implements org.apache.thrift.TBase<getPermissionType_args, getPermissionType_args._Fields>, java.io.Serializable, Cloneable, Comparable<getPermissionType_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getPermissionType_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField PERMISSION_TYPE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("permissionTypeId", org.apache.thrift.protocol.TType.STRING, (short)2);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getPermissionType_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getPermissionType_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String permissionTypeId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      PERMISSION_TYPE_ID((short)2, "permissionTypeId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // PERMISSION_TYPE_ID
            return PERMISSION_TYPE_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.PERMISSION_TYPE_ID, new org.apache.thrift.meta_data.FieldMetaData("permissionTypeId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getPermissionType_args.class, metaDataMap);
    }

    public getPermissionType_args() {
    }

    public getPermissionType_args(
      String domainId,
      String permissionTypeId)
    {
      this();
      this.domainId = domainId;
      this.permissionTypeId = permissionTypeId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getPermissionType_args(getPermissionType_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetPermissionTypeId()) {
        this.permissionTypeId = other.permissionTypeId;
      }
    }

    public getPermissionType_args deepCopy() {
      return new getPermissionType_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.permissionTypeId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getPermissionType_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getPermissionTypeId() {
      return this.permissionTypeId;
    }

    public getPermissionType_args setPermissionTypeId(String permissionTypeId) {
      this.permissionTypeId = permissionTypeId;
      return this;
    }

    public void unsetPermissionTypeId() {
      this.permissionTypeId = null;
    }

    /** Returns true if field permissionTypeId is set (has been assigned a value) and false otherwise */
    public boolean isSetPermissionTypeId() {
      return this.permissionTypeId != null;
    }

    public void setPermissionTypeIdIsSet(boolean value) {
      if (!value) {
        this.permissionTypeId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case PERMISSION_TYPE_ID:
        if (value == null) {
          unsetPermissionTypeId();
        } else {
          setPermissionTypeId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case PERMISSION_TYPE_ID:
        return getPermissionTypeId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case PERMISSION_TYPE_ID:
        return isSetPermissionTypeId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getPermissionType_args)
        return this.equals((getPermissionType_args)that);
      return false;
    }

    public boolean equals(getPermissionType_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_permissionTypeId = true && this.isSetPermissionTypeId();
      boolean that_present_permissionTypeId = true && that.isSetPermissionTypeId();
      if (this_present_permissionTypeId || that_present_permissionTypeId) {
        if (!(this_present_permissionTypeId && that_present_permissionTypeId))
          return false;
        if (!this.permissionTypeId.equals(that.permissionTypeId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_permissionTypeId = true && (isSetPermissionTypeId());
      list.add(present_permissionTypeId);
      if (present_permissionTypeId)
        list.add(permissionTypeId);

      return list.hashCode();
    }

    @Override
    public int compareTo(getPermissionType_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetPermissionTypeId()).compareTo(other.isSetPermissionTypeId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetPermissionTypeId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.permissionTypeId, other.permissionTypeId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getPermissionType_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("permissionTypeId:");
      if (this.permissionTypeId == null) {
        sb.append("null");
      } else {
        sb.append(this.permissionTypeId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (permissionTypeId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'permissionTypeId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getPermissionType_argsStandardSchemeFactory implements SchemeFactory {
      public getPermissionType_argsStandardScheme getScheme() {
        return new getPermissionType_argsStandardScheme();
      }
    }

    private static class getPermissionType_argsStandardScheme extends StandardScheme<getPermissionType_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getPermissionType_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // PERMISSION_TYPE_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.permissionTypeId = iprot.readString();
                struct.setPermissionTypeIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getPermissionType_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.permissionTypeId != null) {
          oprot.writeFieldBegin(PERMISSION_TYPE_ID_FIELD_DESC);
          oprot.writeString(struct.permissionTypeId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getPermissionType_argsTupleSchemeFactory implements SchemeFactory {
      public getPermissionType_argsTupleScheme getScheme() {
        return new getPermissionType_argsTupleScheme();
      }
    }

    private static class getPermissionType_argsTupleScheme extends TupleScheme<getPermissionType_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getPermissionType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.permissionTypeId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getPermissionType_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.permissionTypeId = iprot.readString();
        struct.setPermissionTypeIdIsSet(true);
      }
    }

  }

  public static class getPermissionType_result implements org.apache.thrift.TBase<getPermissionType_result, getPermissionType_result._Fields>, java.io.Serializable, Cloneable, Comparable<getPermissionType_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getPermissionType_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getPermissionType_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getPermissionType_resultTupleSchemeFactory());
    }

    public org.apache.airavata.sharing.registry.models.PermissionType success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.PermissionType.class)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getPermissionType_result.class, metaDataMap);
    }

    public getPermissionType_result() {
    }

    public getPermissionType_result(
      org.apache.airavata.sharing.registry.models.PermissionType success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getPermissionType_result(getPermissionType_result other) {
      if (other.isSetSuccess()) {
        this.success = new org.apache.airavata.sharing.registry.models.PermissionType(other.success);
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getPermissionType_result deepCopy() {
      return new getPermissionType_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public org.apache.airavata.sharing.registry.models.PermissionType getSuccess() {
      return this.success;
    }

    public getPermissionType_result setSuccess(org.apache.airavata.sharing.registry.models.PermissionType success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getPermissionType_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((org.apache.airavata.sharing.registry.models.PermissionType)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getPermissionType_result)
        return this.equals((getPermissionType_result)that);
      return false;
    }

    public boolean equals(getPermissionType_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getPermissionType_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getPermissionType_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
      if (success != null) {
        success.validate();
      }
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getPermissionType_resultStandardSchemeFactory implements SchemeFactory {
      public getPermissionType_resultStandardScheme getScheme() {
        return new getPermissionType_resultStandardScheme();
      }
    }

    private static class getPermissionType_resultStandardScheme extends StandardScheme<getPermissionType_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getPermissionType_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.success = new org.apache.airavata.sharing.registry.models.PermissionType();
                struct.success.read(iprot);
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getPermissionType_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          struct.success.write(oprot);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getPermissionType_resultTupleSchemeFactory implements SchemeFactory {
      public getPermissionType_resultTupleScheme getScheme() {
        return new getPermissionType_resultTupleScheme();
      }
    }

    private static class getPermissionType_resultTupleScheme extends TupleScheme<getPermissionType_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getPermissionType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          struct.success.write(oprot);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getPermissionType_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = new org.apache.airavata.sharing.registry.models.PermissionType();
          struct.success.read(iprot);
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class getPermissionTypes_args implements org.apache.thrift.TBase<getPermissionTypes_args, getPermissionTypes_args._Fields>, java.io.Serializable, Cloneable, Comparable<getPermissionTypes_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getPermissionTypes_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField OFFSET_FIELD_DESC = new org.apache.thrift.protocol.TField("offset", org.apache.thrift.protocol.TType.I32, (short)2);
    private static final org.apache.thrift.protocol.TField LIMIT_FIELD_DESC = new org.apache.thrift.protocol.TField("limit", org.apache.thrift.protocol.TType.I32, (short)3);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getPermissionTypes_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getPermissionTypes_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public int offset; // required
    public int limit; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      OFFSET((short)2, "offset"),
      LIMIT((short)3, "limit");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // OFFSET
            return OFFSET;
          case 3: // LIMIT
            return LIMIT;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __OFFSET_ISSET_ID = 0;
    private static final int __LIMIT_ISSET_ID = 1;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.OFFSET, new org.apache.thrift.meta_data.FieldMetaData("offset", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      tmpMap.put(_Fields.LIMIT, new org.apache.thrift.meta_data.FieldMetaData("limit", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getPermissionTypes_args.class, metaDataMap);
    }

    public getPermissionTypes_args() {
    }

    public getPermissionTypes_args(
      String domainId,
      int offset,
      int limit)
    {
      this();
      this.domainId = domainId;
      this.offset = offset;
      setOffsetIsSet(true);
      this.limit = limit;
      setLimitIsSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getPermissionTypes_args(getPermissionTypes_args other) {
      __isset_bitfield = other.__isset_bitfield;
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      this.offset = other.offset;
      this.limit = other.limit;
    }

    public getPermissionTypes_args deepCopy() {
      return new getPermissionTypes_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      setOffsetIsSet(false);
      this.offset = 0;
      setLimitIsSet(false);
      this.limit = 0;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public getPermissionTypes_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public int getOffset() {
      return this.offset;
    }

    public getPermissionTypes_args setOffset(int offset) {
      this.offset = offset;
      setOffsetIsSet(true);
      return this;
    }

    public void unsetOffset() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    /** Returns true if field offset is set (has been assigned a value) and false otherwise */
    public boolean isSetOffset() {
      return EncodingUtils.testBit(__isset_bitfield, __OFFSET_ISSET_ID);
    }

    public void setOffsetIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __OFFSET_ISSET_ID, value);
    }

    public int getLimit() {
      return this.limit;
    }

    public getPermissionTypes_args setLimit(int limit) {
      this.limit = limit;
      setLimitIsSet(true);
      return this;
    }

    public void unsetLimit() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    /** Returns true if field limit is set (has been assigned a value) and false otherwise */
    public boolean isSetLimit() {
      return EncodingUtils.testBit(__isset_bitfield, __LIMIT_ISSET_ID);
    }

    public void setLimitIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __LIMIT_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case OFFSET:
        if (value == null) {
          unsetOffset();
        } else {
          setOffset((Integer)value);
        }
        break;

      case LIMIT:
        if (value == null) {
          unsetLimit();
        } else {
          setLimit((Integer)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case OFFSET:
        return getOffset();

      case LIMIT:
        return getLimit();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case OFFSET:
        return isSetOffset();
      case LIMIT:
        return isSetLimit();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getPermissionTypes_args)
        return this.equals((getPermissionTypes_args)that);
      return false;
    }

    public boolean equals(getPermissionTypes_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_offset = true;
      boolean that_present_offset = true;
      if (this_present_offset || that_present_offset) {
        if (!(this_present_offset && that_present_offset))
          return false;
        if (this.offset != that.offset)
          return false;
      }

      boolean this_present_limit = true;
      boolean that_present_limit = true;
      if (this_present_limit || that_present_limit) {
        if (!(this_present_limit && that_present_limit))
          return false;
        if (this.limit != that.limit)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_offset = true;
      list.add(present_offset);
      if (present_offset)
        list.add(offset);

      boolean present_limit = true;
      list.add(present_limit);
      if (present_limit)
        list.add(limit);

      return list.hashCode();
    }

    @Override
    public int compareTo(getPermissionTypes_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetOffset()).compareTo(other.isSetOffset());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetOffset()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.offset, other.offset);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetLimit()).compareTo(other.isSetLimit());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetLimit()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.limit, other.limit);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getPermissionTypes_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("offset:");
      sb.append(this.offset);
      first = false;
      if (!first) sb.append(", ");
      sb.append("limit:");
      sb.append(this.limit);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      // alas, we cannot check 'offset' because it's a primitive and you chose the non-beans generator.
      // alas, we cannot check 'limit' because it's a primitive and you chose the non-beans generator.
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getPermissionTypes_argsStandardSchemeFactory implements SchemeFactory {
      public getPermissionTypes_argsStandardScheme getScheme() {
        return new getPermissionTypes_argsStandardScheme();
      }
    }

    private static class getPermissionTypes_argsStandardScheme extends StandardScheme<getPermissionTypes_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getPermissionTypes_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // OFFSET
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.offset = iprot.readI32();
                struct.setOffsetIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // LIMIT
              if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
                struct.limit = iprot.readI32();
                struct.setLimitIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        if (!struct.isSetOffset()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'offset' was not found in serialized data! Struct: " + toString());
        }
        if (!struct.isSetLimit()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'limit' was not found in serialized data! Struct: " + toString());
        }
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getPermissionTypes_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldBegin(OFFSET_FIELD_DESC);
        oprot.writeI32(struct.offset);
        oprot.writeFieldEnd();
        oprot.writeFieldBegin(LIMIT_FIELD_DESC);
        oprot.writeI32(struct.limit);
        oprot.writeFieldEnd();
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getPermissionTypes_argsTupleSchemeFactory implements SchemeFactory {
      public getPermissionTypes_argsTupleScheme getScheme() {
        return new getPermissionTypes_argsTupleScheme();
      }
    }

    private static class getPermissionTypes_argsTupleScheme extends TupleScheme<getPermissionTypes_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getPermissionTypes_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeI32(struct.offset);
        oprot.writeI32(struct.limit);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getPermissionTypes_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.offset = iprot.readI32();
        struct.setOffsetIsSet(true);
        struct.limit = iprot.readI32();
        struct.setLimitIsSet(true);
      }
    }

  }

  public static class getPermissionTypes_result implements org.apache.thrift.TBase<getPermissionTypes_result, getPermissionTypes_result._Fields>, java.io.Serializable, Cloneable, Comparable<getPermissionTypes_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getPermissionTypes_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new getPermissionTypes_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new getPermissionTypes_resultTupleSchemeFactory());
    }

    public List<org.apache.airavata.sharing.registry.models.PermissionType> success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, org.apache.airavata.sharing.registry.models.PermissionType.class))));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getPermissionTypes_result.class, metaDataMap);
    }

    public getPermissionTypes_result() {
    }

    public getPermissionTypes_result(
      List<org.apache.airavata.sharing.registry.models.PermissionType> success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public getPermissionTypes_result(getPermissionTypes_result other) {
      if (other.isSetSuccess()) {
        List<org.apache.airavata.sharing.registry.models.PermissionType> __this__success = new ArrayList<org.apache.airavata.sharing.registry.models.PermissionType>(other.success.size());
        for (org.apache.airavata.sharing.registry.models.PermissionType other_element : other.success) {
          __this__success.add(new org.apache.airavata.sharing.registry.models.PermissionType(other_element));
        }
        this.success = __this__success;
      }
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public getPermissionTypes_result deepCopy() {
      return new getPermissionTypes_result(this);
    }

    @Override
    public void clear() {
      this.success = null;
      this.sre = null;
    }

    public int getSuccessSize() {
      return (this.success == null) ? 0 : this.success.size();
    }

    public java.util.Iterator<org.apache.airavata.sharing.registry.models.PermissionType> getSuccessIterator() {
      return (this.success == null) ? null : this.success.iterator();
    }

    public void addToSuccess(org.apache.airavata.sharing.registry.models.PermissionType elem) {
      if (this.success == null) {
        this.success = new ArrayList<org.apache.airavata.sharing.registry.models.PermissionType>();
      }
      this.success.add(elem);
    }

    public List<org.apache.airavata.sharing.registry.models.PermissionType> getSuccess() {
      return this.success;
    }

    public getPermissionTypes_result setSuccess(List<org.apache.airavata.sharing.registry.models.PermissionType> success) {
      this.success = success;
      return this;
    }

    public void unsetSuccess() {
      this.success = null;
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return this.success != null;
    }

    public void setSuccessIsSet(boolean value) {
      if (!value) {
        this.success = null;
      }
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public getPermissionTypes_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((List<org.apache.airavata.sharing.registry.models.PermissionType>)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return getSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof getPermissionTypes_result)
        return this.equals((getPermissionTypes_result)that);
      return false;
    }

    public boolean equals(getPermissionTypes_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true && this.isSetSuccess();
      boolean that_present_success = true && that.isSetSuccess();
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (!this.success.equals(that.success))
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true && (isSetSuccess());
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(getPermissionTypes_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("getPermissionTypes_result(");
      boolean first = true;

      sb.append("success:");
      if (this.success == null) {
        sb.append("null");
      } else {
        sb.append(this.success);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class getPermissionTypes_resultStandardSchemeFactory implements SchemeFactory {
      public getPermissionTypes_resultStandardScheme getScheme() {
        return new getPermissionTypes_resultStandardScheme();
      }
    }

    private static class getPermissionTypes_resultStandardScheme extends StandardScheme<getPermissionTypes_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, getPermissionTypes_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list112 = iprot.readListBegin();
                  struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.PermissionType>(_list112.size);
                  org.apache.airavata.sharing.registry.models.PermissionType _elem113;
                  for (int _i114 = 0; _i114 < _list112.size; ++_i114)
                  {
                    _elem113 = new org.apache.airavata.sharing.registry.models.PermissionType();
                    _elem113.read(iprot);
                    struct.success.add(_elem113);
                  }
                  iprot.readListEnd();
                }
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, getPermissionTypes_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.success != null) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.success.size()));
            for (org.apache.airavata.sharing.registry.models.PermissionType _iter115 : struct.success)
            {
              _iter115.write(oprot);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class getPermissionTypes_resultTupleSchemeFactory implements SchemeFactory {
      public getPermissionTypes_resultTupleScheme getScheme() {
        return new getPermissionTypes_resultTupleScheme();
      }
    }

    private static class getPermissionTypes_resultTupleScheme extends TupleScheme<getPermissionTypes_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, getPermissionTypes_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          {
            oprot.writeI32(struct.success.size());
            for (org.apache.airavata.sharing.registry.models.PermissionType _iter116 : struct.success)
            {
              _iter116.write(oprot);
            }
          }
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, getPermissionTypes_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          {
            org.apache.thrift.protocol.TList _list117 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
            struct.success = new ArrayList<org.apache.airavata.sharing.registry.models.PermissionType>(_list117.size);
            org.apache.airavata.sharing.registry.models.PermissionType _elem118;
            for (int _i119 = 0; _i119 < _list117.size; ++_i119)
            {
              _elem118 = new org.apache.airavata.sharing.registry.models.PermissionType();
              _elem118.read(iprot);
              struct.success.add(_elem118);
            }
          }
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class shareEntityWithUsers_args implements org.apache.thrift.TBase<shareEntityWithUsers_args, shareEntityWithUsers_args._Fields>, java.io.Serializable, Cloneable, Comparable<shareEntityWithUsers_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("shareEntityWithUsers_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField ENTITY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("entityId", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField USER_LIST_FIELD_DESC = new org.apache.thrift.protocol.TField("userList", org.apache.thrift.protocol.TType.LIST, (short)3);
    private static final org.apache.thrift.protocol.TField PERSSION_TYPE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("perssionTypeId", org.apache.thrift.protocol.TType.STRING, (short)4);
    private static final org.apache.thrift.protocol.TField CASCADE_PERMISSION_FIELD_DESC = new org.apache.thrift.protocol.TField("cascadePermission", org.apache.thrift.protocol.TType.BOOL, (short)5);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new shareEntityWithUsers_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new shareEntityWithUsers_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String entityId; // required
    public List<String> userList; // required
    public String perssionTypeId; // required
    public boolean cascadePermission; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      ENTITY_ID((short)2, "entityId"),
      USER_LIST((short)3, "userList"),
      PERSSION_TYPE_ID((short)4, "perssionTypeId"),
      CASCADE_PERMISSION((short)5, "cascadePermission");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // ENTITY_ID
            return ENTITY_ID;
          case 3: // USER_LIST
            return USER_LIST;
          case 4: // PERSSION_TYPE_ID
            return PERSSION_TYPE_ID;
          case 5: // CASCADE_PERMISSION
            return CASCADE_PERMISSION;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __CASCADEPERMISSION_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.ENTITY_ID, new org.apache.thrift.meta_data.FieldMetaData("entityId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.USER_LIST, new org.apache.thrift.meta_data.FieldMetaData("userList", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
      tmpMap.put(_Fields.PERSSION_TYPE_ID, new org.apache.thrift.meta_data.FieldMetaData("perssionTypeId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.CASCADE_PERMISSION, new org.apache.thrift.meta_data.FieldMetaData("cascadePermission", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(shareEntityWithUsers_args.class, metaDataMap);
    }

    public shareEntityWithUsers_args() {
    }

    public shareEntityWithUsers_args(
      String domainId,
      String entityId,
      List<String> userList,
      String perssionTypeId,
      boolean cascadePermission)
    {
      this();
      this.domainId = domainId;
      this.entityId = entityId;
      this.userList = userList;
      this.perssionTypeId = perssionTypeId;
      this.cascadePermission = cascadePermission;
      setCascadePermissionIsSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public shareEntityWithUsers_args(shareEntityWithUsers_args other) {
      __isset_bitfield = other.__isset_bitfield;
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetEntityId()) {
        this.entityId = other.entityId;
      }
      if (other.isSetUserList()) {
        List<String> __this__userList = new ArrayList<String>(other.userList);
        this.userList = __this__userList;
      }
      if (other.isSetPerssionTypeId()) {
        this.perssionTypeId = other.perssionTypeId;
      }
      this.cascadePermission = other.cascadePermission;
    }

    public shareEntityWithUsers_args deepCopy() {
      return new shareEntityWithUsers_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.entityId = null;
      this.userList = null;
      this.perssionTypeId = null;
      setCascadePermissionIsSet(false);
      this.cascadePermission = false;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public shareEntityWithUsers_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getEntityId() {
      return this.entityId;
    }

    public shareEntityWithUsers_args setEntityId(String entityId) {
      this.entityId = entityId;
      return this;
    }

    public void unsetEntityId() {
      this.entityId = null;
    }

    /** Returns true if field entityId is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityId() {
      return this.entityId != null;
    }

    public void setEntityIdIsSet(boolean value) {
      if (!value) {
        this.entityId = null;
      }
    }

    public int getUserListSize() {
      return (this.userList == null) ? 0 : this.userList.size();
    }

    public java.util.Iterator<String> getUserListIterator() {
      return (this.userList == null) ? null : this.userList.iterator();
    }

    public void addToUserList(String elem) {
      if (this.userList == null) {
        this.userList = new ArrayList<String>();
      }
      this.userList.add(elem);
    }

    public List<String> getUserList() {
      return this.userList;
    }

    public shareEntityWithUsers_args setUserList(List<String> userList) {
      this.userList = userList;
      return this;
    }

    public void unsetUserList() {
      this.userList = null;
    }

    /** Returns true if field userList is set (has been assigned a value) and false otherwise */
    public boolean isSetUserList() {
      return this.userList != null;
    }

    public void setUserListIsSet(boolean value) {
      if (!value) {
        this.userList = null;
      }
    }

    public String getPerssionTypeId() {
      return this.perssionTypeId;
    }

    public shareEntityWithUsers_args setPerssionTypeId(String perssionTypeId) {
      this.perssionTypeId = perssionTypeId;
      return this;
    }

    public void unsetPerssionTypeId() {
      this.perssionTypeId = null;
    }

    /** Returns true if field perssionTypeId is set (has been assigned a value) and false otherwise */
    public boolean isSetPerssionTypeId() {
      return this.perssionTypeId != null;
    }

    public void setPerssionTypeIdIsSet(boolean value) {
      if (!value) {
        this.perssionTypeId = null;
      }
    }

    public boolean isCascadePermission() {
      return this.cascadePermission;
    }

    public shareEntityWithUsers_args setCascadePermission(boolean cascadePermission) {
      this.cascadePermission = cascadePermission;
      setCascadePermissionIsSet(true);
      return this;
    }

    public void unsetCascadePermission() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __CASCADEPERMISSION_ISSET_ID);
    }

    /** Returns true if field cascadePermission is set (has been assigned a value) and false otherwise */
    public boolean isSetCascadePermission() {
      return EncodingUtils.testBit(__isset_bitfield, __CASCADEPERMISSION_ISSET_ID);
    }

    public void setCascadePermissionIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __CASCADEPERMISSION_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case ENTITY_ID:
        if (value == null) {
          unsetEntityId();
        } else {
          setEntityId((String)value);
        }
        break;

      case USER_LIST:
        if (value == null) {
          unsetUserList();
        } else {
          setUserList((List<String>)value);
        }
        break;

      case PERSSION_TYPE_ID:
        if (value == null) {
          unsetPerssionTypeId();
        } else {
          setPerssionTypeId((String)value);
        }
        break;

      case CASCADE_PERMISSION:
        if (value == null) {
          unsetCascadePermission();
        } else {
          setCascadePermission((Boolean)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case ENTITY_ID:
        return getEntityId();

      case USER_LIST:
        return getUserList();

      case PERSSION_TYPE_ID:
        return getPerssionTypeId();

      case CASCADE_PERMISSION:
        return isCascadePermission();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case ENTITY_ID:
        return isSetEntityId();
      case USER_LIST:
        return isSetUserList();
      case PERSSION_TYPE_ID:
        return isSetPerssionTypeId();
      case CASCADE_PERMISSION:
        return isSetCascadePermission();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof shareEntityWithUsers_args)
        return this.equals((shareEntityWithUsers_args)that);
      return false;
    }

    public boolean equals(shareEntityWithUsers_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_entityId = true && this.isSetEntityId();
      boolean that_present_entityId = true && that.isSetEntityId();
      if (this_present_entityId || that_present_entityId) {
        if (!(this_present_entityId && that_present_entityId))
          return false;
        if (!this.entityId.equals(that.entityId))
          return false;
      }

      boolean this_present_userList = true && this.isSetUserList();
      boolean that_present_userList = true && that.isSetUserList();
      if (this_present_userList || that_present_userList) {
        if (!(this_present_userList && that_present_userList))
          return false;
        if (!this.userList.equals(that.userList))
          return false;
      }

      boolean this_present_perssionTypeId = true && this.isSetPerssionTypeId();
      boolean that_present_perssionTypeId = true && that.isSetPerssionTypeId();
      if (this_present_perssionTypeId || that_present_perssionTypeId) {
        if (!(this_present_perssionTypeId && that_present_perssionTypeId))
          return false;
        if (!this.perssionTypeId.equals(that.perssionTypeId))
          return false;
      }

      boolean this_present_cascadePermission = true;
      boolean that_present_cascadePermission = true;
      if (this_present_cascadePermission || that_present_cascadePermission) {
        if (!(this_present_cascadePermission && that_present_cascadePermission))
          return false;
        if (this.cascadePermission != that.cascadePermission)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_entityId = true && (isSetEntityId());
      list.add(present_entityId);
      if (present_entityId)
        list.add(entityId);

      boolean present_userList = true && (isSetUserList());
      list.add(present_userList);
      if (present_userList)
        list.add(userList);

      boolean present_perssionTypeId = true && (isSetPerssionTypeId());
      list.add(present_perssionTypeId);
      if (present_perssionTypeId)
        list.add(perssionTypeId);

      boolean present_cascadePermission = true;
      list.add(present_cascadePermission);
      if (present_cascadePermission)
        list.add(cascadePermission);

      return list.hashCode();
    }

    @Override
    public int compareTo(shareEntityWithUsers_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetEntityId()).compareTo(other.isSetEntityId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityId, other.entityId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetUserList()).compareTo(other.isSetUserList());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetUserList()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.userList, other.userList);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetPerssionTypeId()).compareTo(other.isSetPerssionTypeId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetPerssionTypeId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.perssionTypeId, other.perssionTypeId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetCascadePermission()).compareTo(other.isSetCascadePermission());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetCascadePermission()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.cascadePermission, other.cascadePermission);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("shareEntityWithUsers_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("entityId:");
      if (this.entityId == null) {
        sb.append("null");
      } else {
        sb.append(this.entityId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("userList:");
      if (this.userList == null) {
        sb.append("null");
      } else {
        sb.append(this.userList);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("perssionTypeId:");
      if (this.perssionTypeId == null) {
        sb.append("null");
      } else {
        sb.append(this.perssionTypeId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("cascadePermission:");
      sb.append(this.cascadePermission);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (entityId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityId' was not present! Struct: " + toString());
      }
      if (userList == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'userList' was not present! Struct: " + toString());
      }
      if (perssionTypeId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'perssionTypeId' was not present! Struct: " + toString());
      }
      // alas, we cannot check 'cascadePermission' because it's a primitive and you chose the non-beans generator.
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class shareEntityWithUsers_argsStandardSchemeFactory implements SchemeFactory {
      public shareEntityWithUsers_argsStandardScheme getScheme() {
        return new shareEntityWithUsers_argsStandardScheme();
      }
    }

    private static class shareEntityWithUsers_argsStandardScheme extends StandardScheme<shareEntityWithUsers_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, shareEntityWithUsers_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ENTITY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.entityId = iprot.readString();
                struct.setEntityIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // USER_LIST
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list120 = iprot.readListBegin();
                  struct.userList = new ArrayList<String>(_list120.size);
                  String _elem121;
                  for (int _i122 = 0; _i122 < _list120.size; ++_i122)
                  {
                    _elem121 = iprot.readString();
                    struct.userList.add(_elem121);
                  }
                  iprot.readListEnd();
                }
                struct.setUserListIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 4: // PERSSION_TYPE_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.perssionTypeId = iprot.readString();
                struct.setPerssionTypeIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 5: // CASCADE_PERMISSION
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.cascadePermission = iprot.readBool();
                struct.setCascadePermissionIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        if (!struct.isSetCascadePermission()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'cascadePermission' was not found in serialized data! Struct: " + toString());
        }
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, shareEntityWithUsers_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.entityId != null) {
          oprot.writeFieldBegin(ENTITY_ID_FIELD_DESC);
          oprot.writeString(struct.entityId);
          oprot.writeFieldEnd();
        }
        if (struct.userList != null) {
          oprot.writeFieldBegin(USER_LIST_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.userList.size()));
            for (String _iter123 : struct.userList)
            {
              oprot.writeString(_iter123);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.perssionTypeId != null) {
          oprot.writeFieldBegin(PERSSION_TYPE_ID_FIELD_DESC);
          oprot.writeString(struct.perssionTypeId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldBegin(CASCADE_PERMISSION_FIELD_DESC);
        oprot.writeBool(struct.cascadePermission);
        oprot.writeFieldEnd();
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class shareEntityWithUsers_argsTupleSchemeFactory implements SchemeFactory {
      public shareEntityWithUsers_argsTupleScheme getScheme() {
        return new shareEntityWithUsers_argsTupleScheme();
      }
    }

    private static class shareEntityWithUsers_argsTupleScheme extends TupleScheme<shareEntityWithUsers_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, shareEntityWithUsers_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.entityId);
        {
          oprot.writeI32(struct.userList.size());
          for (String _iter124 : struct.userList)
          {
            oprot.writeString(_iter124);
          }
        }
        oprot.writeString(struct.perssionTypeId);
        oprot.writeBool(struct.cascadePermission);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, shareEntityWithUsers_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.entityId = iprot.readString();
        struct.setEntityIdIsSet(true);
        {
          org.apache.thrift.protocol.TList _list125 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
          struct.userList = new ArrayList<String>(_list125.size);
          String _elem126;
          for (int _i127 = 0; _i127 < _list125.size; ++_i127)
          {
            _elem126 = iprot.readString();
            struct.userList.add(_elem126);
          }
        }
        struct.setUserListIsSet(true);
        struct.perssionTypeId = iprot.readString();
        struct.setPerssionTypeIdIsSet(true);
        struct.cascadePermission = iprot.readBool();
        struct.setCascadePermissionIsSet(true);
      }
    }

  }

  public static class shareEntityWithUsers_result implements org.apache.thrift.TBase<shareEntityWithUsers_result, shareEntityWithUsers_result._Fields>, java.io.Serializable, Cloneable, Comparable<shareEntityWithUsers_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("shareEntityWithUsers_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new shareEntityWithUsers_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new shareEntityWithUsers_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(shareEntityWithUsers_result.class, metaDataMap);
    }

    public shareEntityWithUsers_result() {
    }

    public shareEntityWithUsers_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public shareEntityWithUsers_result(shareEntityWithUsers_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public shareEntityWithUsers_result deepCopy() {
      return new shareEntityWithUsers_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public shareEntityWithUsers_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public shareEntityWithUsers_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof shareEntityWithUsers_result)
        return this.equals((shareEntityWithUsers_result)that);
      return false;
    }

    public boolean equals(shareEntityWithUsers_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(shareEntityWithUsers_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("shareEntityWithUsers_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class shareEntityWithUsers_resultStandardSchemeFactory implements SchemeFactory {
      public shareEntityWithUsers_resultStandardScheme getScheme() {
        return new shareEntityWithUsers_resultStandardScheme();
      }
    }

    private static class shareEntityWithUsers_resultStandardScheme extends StandardScheme<shareEntityWithUsers_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, shareEntityWithUsers_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, shareEntityWithUsers_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class shareEntityWithUsers_resultTupleSchemeFactory implements SchemeFactory {
      public shareEntityWithUsers_resultTupleScheme getScheme() {
        return new shareEntityWithUsers_resultTupleScheme();
      }
    }

    private static class shareEntityWithUsers_resultTupleScheme extends TupleScheme<shareEntityWithUsers_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, shareEntityWithUsers_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, shareEntityWithUsers_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class revokeEntitySharingFromUsers_args implements org.apache.thrift.TBase<revokeEntitySharingFromUsers_args, revokeEntitySharingFromUsers_args._Fields>, java.io.Serializable, Cloneable, Comparable<revokeEntitySharingFromUsers_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("revokeEntitySharingFromUsers_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField ENTITY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("entityId", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField USER_LIST_FIELD_DESC = new org.apache.thrift.protocol.TField("userList", org.apache.thrift.protocol.TType.LIST, (short)3);
    private static final org.apache.thrift.protocol.TField PERSSION_TYPE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("perssionTypeId", org.apache.thrift.protocol.TType.STRING, (short)4);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new revokeEntitySharingFromUsers_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new revokeEntitySharingFromUsers_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String entityId; // required
    public List<String> userList; // required
    public String perssionTypeId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      ENTITY_ID((short)2, "entityId"),
      USER_LIST((short)3, "userList"),
      PERSSION_TYPE_ID((short)4, "perssionTypeId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // ENTITY_ID
            return ENTITY_ID;
          case 3: // USER_LIST
            return USER_LIST;
          case 4: // PERSSION_TYPE_ID
            return PERSSION_TYPE_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.ENTITY_ID, new org.apache.thrift.meta_data.FieldMetaData("entityId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.USER_LIST, new org.apache.thrift.meta_data.FieldMetaData("userList", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
      tmpMap.put(_Fields.PERSSION_TYPE_ID, new org.apache.thrift.meta_data.FieldMetaData("perssionTypeId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(revokeEntitySharingFromUsers_args.class, metaDataMap);
    }

    public revokeEntitySharingFromUsers_args() {
    }

    public revokeEntitySharingFromUsers_args(
      String domainId,
      String entityId,
      List<String> userList,
      String perssionTypeId)
    {
      this();
      this.domainId = domainId;
      this.entityId = entityId;
      this.userList = userList;
      this.perssionTypeId = perssionTypeId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public revokeEntitySharingFromUsers_args(revokeEntitySharingFromUsers_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetEntityId()) {
        this.entityId = other.entityId;
      }
      if (other.isSetUserList()) {
        List<String> __this__userList = new ArrayList<String>(other.userList);
        this.userList = __this__userList;
      }
      if (other.isSetPerssionTypeId()) {
        this.perssionTypeId = other.perssionTypeId;
      }
    }

    public revokeEntitySharingFromUsers_args deepCopy() {
      return new revokeEntitySharingFromUsers_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.entityId = null;
      this.userList = null;
      this.perssionTypeId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public revokeEntitySharingFromUsers_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getEntityId() {
      return this.entityId;
    }

    public revokeEntitySharingFromUsers_args setEntityId(String entityId) {
      this.entityId = entityId;
      return this;
    }

    public void unsetEntityId() {
      this.entityId = null;
    }

    /** Returns true if field entityId is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityId() {
      return this.entityId != null;
    }

    public void setEntityIdIsSet(boolean value) {
      if (!value) {
        this.entityId = null;
      }
    }

    public int getUserListSize() {
      return (this.userList == null) ? 0 : this.userList.size();
    }

    public java.util.Iterator<String> getUserListIterator() {
      return (this.userList == null) ? null : this.userList.iterator();
    }

    public void addToUserList(String elem) {
      if (this.userList == null) {
        this.userList = new ArrayList<String>();
      }
      this.userList.add(elem);
    }

    public List<String> getUserList() {
      return this.userList;
    }

    public revokeEntitySharingFromUsers_args setUserList(List<String> userList) {
      this.userList = userList;
      return this;
    }

    public void unsetUserList() {
      this.userList = null;
    }

    /** Returns true if field userList is set (has been assigned a value) and false otherwise */
    public boolean isSetUserList() {
      return this.userList != null;
    }

    public void setUserListIsSet(boolean value) {
      if (!value) {
        this.userList = null;
      }
    }

    public String getPerssionTypeId() {
      return this.perssionTypeId;
    }

    public revokeEntitySharingFromUsers_args setPerssionTypeId(String perssionTypeId) {
      this.perssionTypeId = perssionTypeId;
      return this;
    }

    public void unsetPerssionTypeId() {
      this.perssionTypeId = null;
    }

    /** Returns true if field perssionTypeId is set (has been assigned a value) and false otherwise */
    public boolean isSetPerssionTypeId() {
      return this.perssionTypeId != null;
    }

    public void setPerssionTypeIdIsSet(boolean value) {
      if (!value) {
        this.perssionTypeId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case ENTITY_ID:
        if (value == null) {
          unsetEntityId();
        } else {
          setEntityId((String)value);
        }
        break;

      case USER_LIST:
        if (value == null) {
          unsetUserList();
        } else {
          setUserList((List<String>)value);
        }
        break;

      case PERSSION_TYPE_ID:
        if (value == null) {
          unsetPerssionTypeId();
        } else {
          setPerssionTypeId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case ENTITY_ID:
        return getEntityId();

      case USER_LIST:
        return getUserList();

      case PERSSION_TYPE_ID:
        return getPerssionTypeId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case ENTITY_ID:
        return isSetEntityId();
      case USER_LIST:
        return isSetUserList();
      case PERSSION_TYPE_ID:
        return isSetPerssionTypeId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof revokeEntitySharingFromUsers_args)
        return this.equals((revokeEntitySharingFromUsers_args)that);
      return false;
    }

    public boolean equals(revokeEntitySharingFromUsers_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_entityId = true && this.isSetEntityId();
      boolean that_present_entityId = true && that.isSetEntityId();
      if (this_present_entityId || that_present_entityId) {
        if (!(this_present_entityId && that_present_entityId))
          return false;
        if (!this.entityId.equals(that.entityId))
          return false;
      }

      boolean this_present_userList = true && this.isSetUserList();
      boolean that_present_userList = true && that.isSetUserList();
      if (this_present_userList || that_present_userList) {
        if (!(this_present_userList && that_present_userList))
          return false;
        if (!this.userList.equals(that.userList))
          return false;
      }

      boolean this_present_perssionTypeId = true && this.isSetPerssionTypeId();
      boolean that_present_perssionTypeId = true && that.isSetPerssionTypeId();
      if (this_present_perssionTypeId || that_present_perssionTypeId) {
        if (!(this_present_perssionTypeId && that_present_perssionTypeId))
          return false;
        if (!this.perssionTypeId.equals(that.perssionTypeId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_entityId = true && (isSetEntityId());
      list.add(present_entityId);
      if (present_entityId)
        list.add(entityId);

      boolean present_userList = true && (isSetUserList());
      list.add(present_userList);
      if (present_userList)
        list.add(userList);

      boolean present_perssionTypeId = true && (isSetPerssionTypeId());
      list.add(present_perssionTypeId);
      if (present_perssionTypeId)
        list.add(perssionTypeId);

      return list.hashCode();
    }

    @Override
    public int compareTo(revokeEntitySharingFromUsers_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetEntityId()).compareTo(other.isSetEntityId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityId, other.entityId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetUserList()).compareTo(other.isSetUserList());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetUserList()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.userList, other.userList);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetPerssionTypeId()).compareTo(other.isSetPerssionTypeId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetPerssionTypeId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.perssionTypeId, other.perssionTypeId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("revokeEntitySharingFromUsers_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("entityId:");
      if (this.entityId == null) {
        sb.append("null");
      } else {
        sb.append(this.entityId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("userList:");
      if (this.userList == null) {
        sb.append("null");
      } else {
        sb.append(this.userList);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("perssionTypeId:");
      if (this.perssionTypeId == null) {
        sb.append("null");
      } else {
        sb.append(this.perssionTypeId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (entityId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityId' was not present! Struct: " + toString());
      }
      if (userList == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'userList' was not present! Struct: " + toString());
      }
      if (perssionTypeId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'perssionTypeId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class revokeEntitySharingFromUsers_argsStandardSchemeFactory implements SchemeFactory {
      public revokeEntitySharingFromUsers_argsStandardScheme getScheme() {
        return new revokeEntitySharingFromUsers_argsStandardScheme();
      }
    }

    private static class revokeEntitySharingFromUsers_argsStandardScheme extends StandardScheme<revokeEntitySharingFromUsers_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, revokeEntitySharingFromUsers_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ENTITY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.entityId = iprot.readString();
                struct.setEntityIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // USER_LIST
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list128 = iprot.readListBegin();
                  struct.userList = new ArrayList<String>(_list128.size);
                  String _elem129;
                  for (int _i130 = 0; _i130 < _list128.size; ++_i130)
                  {
                    _elem129 = iprot.readString();
                    struct.userList.add(_elem129);
                  }
                  iprot.readListEnd();
                }
                struct.setUserListIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 4: // PERSSION_TYPE_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.perssionTypeId = iprot.readString();
                struct.setPerssionTypeIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, revokeEntitySharingFromUsers_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.entityId != null) {
          oprot.writeFieldBegin(ENTITY_ID_FIELD_DESC);
          oprot.writeString(struct.entityId);
          oprot.writeFieldEnd();
        }
        if (struct.userList != null) {
          oprot.writeFieldBegin(USER_LIST_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.userList.size()));
            for (String _iter131 : struct.userList)
            {
              oprot.writeString(_iter131);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.perssionTypeId != null) {
          oprot.writeFieldBegin(PERSSION_TYPE_ID_FIELD_DESC);
          oprot.writeString(struct.perssionTypeId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class revokeEntitySharingFromUsers_argsTupleSchemeFactory implements SchemeFactory {
      public revokeEntitySharingFromUsers_argsTupleScheme getScheme() {
        return new revokeEntitySharingFromUsers_argsTupleScheme();
      }
    }

    private static class revokeEntitySharingFromUsers_argsTupleScheme extends TupleScheme<revokeEntitySharingFromUsers_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, revokeEntitySharingFromUsers_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.entityId);
        {
          oprot.writeI32(struct.userList.size());
          for (String _iter132 : struct.userList)
          {
            oprot.writeString(_iter132);
          }
        }
        oprot.writeString(struct.perssionTypeId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, revokeEntitySharingFromUsers_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.entityId = iprot.readString();
        struct.setEntityIdIsSet(true);
        {
          org.apache.thrift.protocol.TList _list133 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
          struct.userList = new ArrayList<String>(_list133.size);
          String _elem134;
          for (int _i135 = 0; _i135 < _list133.size; ++_i135)
          {
            _elem134 = iprot.readString();
            struct.userList.add(_elem134);
          }
        }
        struct.setUserListIsSet(true);
        struct.perssionTypeId = iprot.readString();
        struct.setPerssionTypeIdIsSet(true);
      }
    }

  }

  public static class revokeEntitySharingFromUsers_result implements org.apache.thrift.TBase<revokeEntitySharingFromUsers_result, revokeEntitySharingFromUsers_result._Fields>, java.io.Serializable, Cloneable, Comparable<revokeEntitySharingFromUsers_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("revokeEntitySharingFromUsers_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new revokeEntitySharingFromUsers_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new revokeEntitySharingFromUsers_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(revokeEntitySharingFromUsers_result.class, metaDataMap);
    }

    public revokeEntitySharingFromUsers_result() {
    }

    public revokeEntitySharingFromUsers_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public revokeEntitySharingFromUsers_result(revokeEntitySharingFromUsers_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public revokeEntitySharingFromUsers_result deepCopy() {
      return new revokeEntitySharingFromUsers_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public revokeEntitySharingFromUsers_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public revokeEntitySharingFromUsers_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof revokeEntitySharingFromUsers_result)
        return this.equals((revokeEntitySharingFromUsers_result)that);
      return false;
    }

    public boolean equals(revokeEntitySharingFromUsers_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(revokeEntitySharingFromUsers_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("revokeEntitySharingFromUsers_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class revokeEntitySharingFromUsers_resultStandardSchemeFactory implements SchemeFactory {
      public revokeEntitySharingFromUsers_resultStandardScheme getScheme() {
        return new revokeEntitySharingFromUsers_resultStandardScheme();
      }
    }

    private static class revokeEntitySharingFromUsers_resultStandardScheme extends StandardScheme<revokeEntitySharingFromUsers_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, revokeEntitySharingFromUsers_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, revokeEntitySharingFromUsers_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class revokeEntitySharingFromUsers_resultTupleSchemeFactory implements SchemeFactory {
      public revokeEntitySharingFromUsers_resultTupleScheme getScheme() {
        return new revokeEntitySharingFromUsers_resultTupleScheme();
      }
    }

    private static class revokeEntitySharingFromUsers_resultTupleScheme extends TupleScheme<revokeEntitySharingFromUsers_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, revokeEntitySharingFromUsers_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, revokeEntitySharingFromUsers_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class shareEntityWithGroups_args implements org.apache.thrift.TBase<shareEntityWithGroups_args, shareEntityWithGroups_args._Fields>, java.io.Serializable, Cloneable, Comparable<shareEntityWithGroups_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("shareEntityWithGroups_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField ENTITY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("entityId", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField GROUP_LIST_FIELD_DESC = new org.apache.thrift.protocol.TField("groupList", org.apache.thrift.protocol.TType.LIST, (short)3);
    private static final org.apache.thrift.protocol.TField PERSSION_TYPE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("perssionTypeId", org.apache.thrift.protocol.TType.STRING, (short)4);
    private static final org.apache.thrift.protocol.TField CASCADE_PERMISSION_FIELD_DESC = new org.apache.thrift.protocol.TField("cascadePermission", org.apache.thrift.protocol.TType.BOOL, (short)5);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new shareEntityWithGroups_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new shareEntityWithGroups_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String entityId; // required
    public List<String> groupList; // required
    public String perssionTypeId; // required
    public boolean cascadePermission; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      ENTITY_ID((short)2, "entityId"),
      GROUP_LIST((short)3, "groupList"),
      PERSSION_TYPE_ID((short)4, "perssionTypeId"),
      CASCADE_PERMISSION((short)5, "cascadePermission");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // ENTITY_ID
            return ENTITY_ID;
          case 3: // GROUP_LIST
            return GROUP_LIST;
          case 4: // PERSSION_TYPE_ID
            return PERSSION_TYPE_ID;
          case 5: // CASCADE_PERMISSION
            return CASCADE_PERMISSION;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __CASCADEPERMISSION_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.ENTITY_ID, new org.apache.thrift.meta_data.FieldMetaData("entityId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.GROUP_LIST, new org.apache.thrift.meta_data.FieldMetaData("groupList", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
      tmpMap.put(_Fields.PERSSION_TYPE_ID, new org.apache.thrift.meta_data.FieldMetaData("perssionTypeId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.CASCADE_PERMISSION, new org.apache.thrift.meta_data.FieldMetaData("cascadePermission", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(shareEntityWithGroups_args.class, metaDataMap);
    }

    public shareEntityWithGroups_args() {
    }

    public shareEntityWithGroups_args(
      String domainId,
      String entityId,
      List<String> groupList,
      String perssionTypeId,
      boolean cascadePermission)
    {
      this();
      this.domainId = domainId;
      this.entityId = entityId;
      this.groupList = groupList;
      this.perssionTypeId = perssionTypeId;
      this.cascadePermission = cascadePermission;
      setCascadePermissionIsSet(true);
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public shareEntityWithGroups_args(shareEntityWithGroups_args other) {
      __isset_bitfield = other.__isset_bitfield;
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetEntityId()) {
        this.entityId = other.entityId;
      }
      if (other.isSetGroupList()) {
        List<String> __this__groupList = new ArrayList<String>(other.groupList);
        this.groupList = __this__groupList;
      }
      if (other.isSetPerssionTypeId()) {
        this.perssionTypeId = other.perssionTypeId;
      }
      this.cascadePermission = other.cascadePermission;
    }

    public shareEntityWithGroups_args deepCopy() {
      return new shareEntityWithGroups_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.entityId = null;
      this.groupList = null;
      this.perssionTypeId = null;
      setCascadePermissionIsSet(false);
      this.cascadePermission = false;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public shareEntityWithGroups_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getEntityId() {
      return this.entityId;
    }

    public shareEntityWithGroups_args setEntityId(String entityId) {
      this.entityId = entityId;
      return this;
    }

    public void unsetEntityId() {
      this.entityId = null;
    }

    /** Returns true if field entityId is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityId() {
      return this.entityId != null;
    }

    public void setEntityIdIsSet(boolean value) {
      if (!value) {
        this.entityId = null;
      }
    }

    public int getGroupListSize() {
      return (this.groupList == null) ? 0 : this.groupList.size();
    }

    public java.util.Iterator<String> getGroupListIterator() {
      return (this.groupList == null) ? null : this.groupList.iterator();
    }

    public void addToGroupList(String elem) {
      if (this.groupList == null) {
        this.groupList = new ArrayList<String>();
      }
      this.groupList.add(elem);
    }

    public List<String> getGroupList() {
      return this.groupList;
    }

    public shareEntityWithGroups_args setGroupList(List<String> groupList) {
      this.groupList = groupList;
      return this;
    }

    public void unsetGroupList() {
      this.groupList = null;
    }

    /** Returns true if field groupList is set (has been assigned a value) and false otherwise */
    public boolean isSetGroupList() {
      return this.groupList != null;
    }

    public void setGroupListIsSet(boolean value) {
      if (!value) {
        this.groupList = null;
      }
    }

    public String getPerssionTypeId() {
      return this.perssionTypeId;
    }

    public shareEntityWithGroups_args setPerssionTypeId(String perssionTypeId) {
      this.perssionTypeId = perssionTypeId;
      return this;
    }

    public void unsetPerssionTypeId() {
      this.perssionTypeId = null;
    }

    /** Returns true if field perssionTypeId is set (has been assigned a value) and false otherwise */
    public boolean isSetPerssionTypeId() {
      return this.perssionTypeId != null;
    }

    public void setPerssionTypeIdIsSet(boolean value) {
      if (!value) {
        this.perssionTypeId = null;
      }
    }

    public boolean isCascadePermission() {
      return this.cascadePermission;
    }

    public shareEntityWithGroups_args setCascadePermission(boolean cascadePermission) {
      this.cascadePermission = cascadePermission;
      setCascadePermissionIsSet(true);
      return this;
    }

    public void unsetCascadePermission() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __CASCADEPERMISSION_ISSET_ID);
    }

    /** Returns true if field cascadePermission is set (has been assigned a value) and false otherwise */
    public boolean isSetCascadePermission() {
      return EncodingUtils.testBit(__isset_bitfield, __CASCADEPERMISSION_ISSET_ID);
    }

    public void setCascadePermissionIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __CASCADEPERMISSION_ISSET_ID, value);
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case ENTITY_ID:
        if (value == null) {
          unsetEntityId();
        } else {
          setEntityId((String)value);
        }
        break;

      case GROUP_LIST:
        if (value == null) {
          unsetGroupList();
        } else {
          setGroupList((List<String>)value);
        }
        break;

      case PERSSION_TYPE_ID:
        if (value == null) {
          unsetPerssionTypeId();
        } else {
          setPerssionTypeId((String)value);
        }
        break;

      case CASCADE_PERMISSION:
        if (value == null) {
          unsetCascadePermission();
        } else {
          setCascadePermission((Boolean)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case ENTITY_ID:
        return getEntityId();

      case GROUP_LIST:
        return getGroupList();

      case PERSSION_TYPE_ID:
        return getPerssionTypeId();

      case CASCADE_PERMISSION:
        return isCascadePermission();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case ENTITY_ID:
        return isSetEntityId();
      case GROUP_LIST:
        return isSetGroupList();
      case PERSSION_TYPE_ID:
        return isSetPerssionTypeId();
      case CASCADE_PERMISSION:
        return isSetCascadePermission();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof shareEntityWithGroups_args)
        return this.equals((shareEntityWithGroups_args)that);
      return false;
    }

    public boolean equals(shareEntityWithGroups_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_entityId = true && this.isSetEntityId();
      boolean that_present_entityId = true && that.isSetEntityId();
      if (this_present_entityId || that_present_entityId) {
        if (!(this_present_entityId && that_present_entityId))
          return false;
        if (!this.entityId.equals(that.entityId))
          return false;
      }

      boolean this_present_groupList = true && this.isSetGroupList();
      boolean that_present_groupList = true && that.isSetGroupList();
      if (this_present_groupList || that_present_groupList) {
        if (!(this_present_groupList && that_present_groupList))
          return false;
        if (!this.groupList.equals(that.groupList))
          return false;
      }

      boolean this_present_perssionTypeId = true && this.isSetPerssionTypeId();
      boolean that_present_perssionTypeId = true && that.isSetPerssionTypeId();
      if (this_present_perssionTypeId || that_present_perssionTypeId) {
        if (!(this_present_perssionTypeId && that_present_perssionTypeId))
          return false;
        if (!this.perssionTypeId.equals(that.perssionTypeId))
          return false;
      }

      boolean this_present_cascadePermission = true;
      boolean that_present_cascadePermission = true;
      if (this_present_cascadePermission || that_present_cascadePermission) {
        if (!(this_present_cascadePermission && that_present_cascadePermission))
          return false;
        if (this.cascadePermission != that.cascadePermission)
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_entityId = true && (isSetEntityId());
      list.add(present_entityId);
      if (present_entityId)
        list.add(entityId);

      boolean present_groupList = true && (isSetGroupList());
      list.add(present_groupList);
      if (present_groupList)
        list.add(groupList);

      boolean present_perssionTypeId = true && (isSetPerssionTypeId());
      list.add(present_perssionTypeId);
      if (present_perssionTypeId)
        list.add(perssionTypeId);

      boolean present_cascadePermission = true;
      list.add(present_cascadePermission);
      if (present_cascadePermission)
        list.add(cascadePermission);

      return list.hashCode();
    }

    @Override
    public int compareTo(shareEntityWithGroups_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetEntityId()).compareTo(other.isSetEntityId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityId, other.entityId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetGroupList()).compareTo(other.isSetGroupList());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetGroupList()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.groupList, other.groupList);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetPerssionTypeId()).compareTo(other.isSetPerssionTypeId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetPerssionTypeId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.perssionTypeId, other.perssionTypeId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetCascadePermission()).compareTo(other.isSetCascadePermission());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetCascadePermission()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.cascadePermission, other.cascadePermission);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("shareEntityWithGroups_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("entityId:");
      if (this.entityId == null) {
        sb.append("null");
      } else {
        sb.append(this.entityId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("groupList:");
      if (this.groupList == null) {
        sb.append("null");
      } else {
        sb.append(this.groupList);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("perssionTypeId:");
      if (this.perssionTypeId == null) {
        sb.append("null");
      } else {
        sb.append(this.perssionTypeId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("cascadePermission:");
      sb.append(this.cascadePermission);
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (entityId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityId' was not present! Struct: " + toString());
      }
      if (groupList == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'groupList' was not present! Struct: " + toString());
      }
      if (perssionTypeId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'perssionTypeId' was not present! Struct: " + toString());
      }
      // alas, we cannot check 'cascadePermission' because it's a primitive and you chose the non-beans generator.
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class shareEntityWithGroups_argsStandardSchemeFactory implements SchemeFactory {
      public shareEntityWithGroups_argsStandardScheme getScheme() {
        return new shareEntityWithGroups_argsStandardScheme();
      }
    }

    private static class shareEntityWithGroups_argsStandardScheme extends StandardScheme<shareEntityWithGroups_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, shareEntityWithGroups_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ENTITY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.entityId = iprot.readString();
                struct.setEntityIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // GROUP_LIST
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list136 = iprot.readListBegin();
                  struct.groupList = new ArrayList<String>(_list136.size);
                  String _elem137;
                  for (int _i138 = 0; _i138 < _list136.size; ++_i138)
                  {
                    _elem137 = iprot.readString();
                    struct.groupList.add(_elem137);
                  }
                  iprot.readListEnd();
                }
                struct.setGroupListIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 4: // PERSSION_TYPE_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.perssionTypeId = iprot.readString();
                struct.setPerssionTypeIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 5: // CASCADE_PERMISSION
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.cascadePermission = iprot.readBool();
                struct.setCascadePermissionIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        if (!struct.isSetCascadePermission()) {
          throw new org.apache.thrift.protocol.TProtocolException("Required field 'cascadePermission' was not found in serialized data! Struct: " + toString());
        }
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, shareEntityWithGroups_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.entityId != null) {
          oprot.writeFieldBegin(ENTITY_ID_FIELD_DESC);
          oprot.writeString(struct.entityId);
          oprot.writeFieldEnd();
        }
        if (struct.groupList != null) {
          oprot.writeFieldBegin(GROUP_LIST_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.groupList.size()));
            for (String _iter139 : struct.groupList)
            {
              oprot.writeString(_iter139);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.perssionTypeId != null) {
          oprot.writeFieldBegin(PERSSION_TYPE_ID_FIELD_DESC);
          oprot.writeString(struct.perssionTypeId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldBegin(CASCADE_PERMISSION_FIELD_DESC);
        oprot.writeBool(struct.cascadePermission);
        oprot.writeFieldEnd();
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class shareEntityWithGroups_argsTupleSchemeFactory implements SchemeFactory {
      public shareEntityWithGroups_argsTupleScheme getScheme() {
        return new shareEntityWithGroups_argsTupleScheme();
      }
    }

    private static class shareEntityWithGroups_argsTupleScheme extends TupleScheme<shareEntityWithGroups_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, shareEntityWithGroups_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.entityId);
        {
          oprot.writeI32(struct.groupList.size());
          for (String _iter140 : struct.groupList)
          {
            oprot.writeString(_iter140);
          }
        }
        oprot.writeString(struct.perssionTypeId);
        oprot.writeBool(struct.cascadePermission);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, shareEntityWithGroups_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.entityId = iprot.readString();
        struct.setEntityIdIsSet(true);
        {
          org.apache.thrift.protocol.TList _list141 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
          struct.groupList = new ArrayList<String>(_list141.size);
          String _elem142;
          for (int _i143 = 0; _i143 < _list141.size; ++_i143)
          {
            _elem142 = iprot.readString();
            struct.groupList.add(_elem142);
          }
        }
        struct.setGroupListIsSet(true);
        struct.perssionTypeId = iprot.readString();
        struct.setPerssionTypeIdIsSet(true);
        struct.cascadePermission = iprot.readBool();
        struct.setCascadePermissionIsSet(true);
      }
    }

  }

  public static class shareEntityWithGroups_result implements org.apache.thrift.TBase<shareEntityWithGroups_result, shareEntityWithGroups_result._Fields>, java.io.Serializable, Cloneable, Comparable<shareEntityWithGroups_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("shareEntityWithGroups_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new shareEntityWithGroups_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new shareEntityWithGroups_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(shareEntityWithGroups_result.class, metaDataMap);
    }

    public shareEntityWithGroups_result() {
    }

    public shareEntityWithGroups_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public shareEntityWithGroups_result(shareEntityWithGroups_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public shareEntityWithGroups_result deepCopy() {
      return new shareEntityWithGroups_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public shareEntityWithGroups_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public shareEntityWithGroups_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof shareEntityWithGroups_result)
        return this.equals((shareEntityWithGroups_result)that);
      return false;
    }

    public boolean equals(shareEntityWithGroups_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(shareEntityWithGroups_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("shareEntityWithGroups_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class shareEntityWithGroups_resultStandardSchemeFactory implements SchemeFactory {
      public shareEntityWithGroups_resultStandardScheme getScheme() {
        return new shareEntityWithGroups_resultStandardScheme();
      }
    }

    private static class shareEntityWithGroups_resultStandardScheme extends StandardScheme<shareEntityWithGroups_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, shareEntityWithGroups_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, shareEntityWithGroups_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class shareEntityWithGroups_resultTupleSchemeFactory implements SchemeFactory {
      public shareEntityWithGroups_resultTupleScheme getScheme() {
        return new shareEntityWithGroups_resultTupleScheme();
      }
    }

    private static class shareEntityWithGroups_resultTupleScheme extends TupleScheme<shareEntityWithGroups_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, shareEntityWithGroups_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, shareEntityWithGroups_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class revokeEntitySharingFromGroups_args implements org.apache.thrift.TBase<revokeEntitySharingFromGroups_args, revokeEntitySharingFromGroups_args._Fields>, java.io.Serializable, Cloneable, Comparable<revokeEntitySharingFromGroups_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("revokeEntitySharingFromGroups_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField ENTITY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("entityId", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField GROUP_LIST_FIELD_DESC = new org.apache.thrift.protocol.TField("groupList", org.apache.thrift.protocol.TType.LIST, (short)3);
    private static final org.apache.thrift.protocol.TField PERSSION_TYPE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("perssionTypeId", org.apache.thrift.protocol.TType.STRING, (short)4);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new revokeEntitySharingFromGroups_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new revokeEntitySharingFromGroups_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String entityId; // required
    public List<String> groupList; // required
    public String perssionTypeId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      ENTITY_ID((short)2, "entityId"),
      GROUP_LIST((short)3, "groupList"),
      PERSSION_TYPE_ID((short)4, "perssionTypeId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // ENTITY_ID
            return ENTITY_ID;
          case 3: // GROUP_LIST
            return GROUP_LIST;
          case 4: // PERSSION_TYPE_ID
            return PERSSION_TYPE_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.ENTITY_ID, new org.apache.thrift.meta_data.FieldMetaData("entityId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.GROUP_LIST, new org.apache.thrift.meta_data.FieldMetaData("groupList", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
              new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
      tmpMap.put(_Fields.PERSSION_TYPE_ID, new org.apache.thrift.meta_data.FieldMetaData("perssionTypeId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(revokeEntitySharingFromGroups_args.class, metaDataMap);
    }

    public revokeEntitySharingFromGroups_args() {
    }

    public revokeEntitySharingFromGroups_args(
      String domainId,
      String entityId,
      List<String> groupList,
      String perssionTypeId)
    {
      this();
      this.domainId = domainId;
      this.entityId = entityId;
      this.groupList = groupList;
      this.perssionTypeId = perssionTypeId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public revokeEntitySharingFromGroups_args(revokeEntitySharingFromGroups_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetEntityId()) {
        this.entityId = other.entityId;
      }
      if (other.isSetGroupList()) {
        List<String> __this__groupList = new ArrayList<String>(other.groupList);
        this.groupList = __this__groupList;
      }
      if (other.isSetPerssionTypeId()) {
        this.perssionTypeId = other.perssionTypeId;
      }
    }

    public revokeEntitySharingFromGroups_args deepCopy() {
      return new revokeEntitySharingFromGroups_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.entityId = null;
      this.groupList = null;
      this.perssionTypeId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public revokeEntitySharingFromGroups_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getEntityId() {
      return this.entityId;
    }

    public revokeEntitySharingFromGroups_args setEntityId(String entityId) {
      this.entityId = entityId;
      return this;
    }

    public void unsetEntityId() {
      this.entityId = null;
    }

    /** Returns true if field entityId is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityId() {
      return this.entityId != null;
    }

    public void setEntityIdIsSet(boolean value) {
      if (!value) {
        this.entityId = null;
      }
    }

    public int getGroupListSize() {
      return (this.groupList == null) ? 0 : this.groupList.size();
    }

    public java.util.Iterator<String> getGroupListIterator() {
      return (this.groupList == null) ? null : this.groupList.iterator();
    }

    public void addToGroupList(String elem) {
      if (this.groupList == null) {
        this.groupList = new ArrayList<String>();
      }
      this.groupList.add(elem);
    }

    public List<String> getGroupList() {
      return this.groupList;
    }

    public revokeEntitySharingFromGroups_args setGroupList(List<String> groupList) {
      this.groupList = groupList;
      return this;
    }

    public void unsetGroupList() {
      this.groupList = null;
    }

    /** Returns true if field groupList is set (has been assigned a value) and false otherwise */
    public boolean isSetGroupList() {
      return this.groupList != null;
    }

    public void setGroupListIsSet(boolean value) {
      if (!value) {
        this.groupList = null;
      }
    }

    public String getPerssionTypeId() {
      return this.perssionTypeId;
    }

    public revokeEntitySharingFromGroups_args setPerssionTypeId(String perssionTypeId) {
      this.perssionTypeId = perssionTypeId;
      return this;
    }

    public void unsetPerssionTypeId() {
      this.perssionTypeId = null;
    }

    /** Returns true if field perssionTypeId is set (has been assigned a value) and false otherwise */
    public boolean isSetPerssionTypeId() {
      return this.perssionTypeId != null;
    }

    public void setPerssionTypeIdIsSet(boolean value) {
      if (!value) {
        this.perssionTypeId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case ENTITY_ID:
        if (value == null) {
          unsetEntityId();
        } else {
          setEntityId((String)value);
        }
        break;

      case GROUP_LIST:
        if (value == null) {
          unsetGroupList();
        } else {
          setGroupList((List<String>)value);
        }
        break;

      case PERSSION_TYPE_ID:
        if (value == null) {
          unsetPerssionTypeId();
        } else {
          setPerssionTypeId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case ENTITY_ID:
        return getEntityId();

      case GROUP_LIST:
        return getGroupList();

      case PERSSION_TYPE_ID:
        return getPerssionTypeId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case ENTITY_ID:
        return isSetEntityId();
      case GROUP_LIST:
        return isSetGroupList();
      case PERSSION_TYPE_ID:
        return isSetPerssionTypeId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof revokeEntitySharingFromGroups_args)
        return this.equals((revokeEntitySharingFromGroups_args)that);
      return false;
    }

    public boolean equals(revokeEntitySharingFromGroups_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_entityId = true && this.isSetEntityId();
      boolean that_present_entityId = true && that.isSetEntityId();
      if (this_present_entityId || that_present_entityId) {
        if (!(this_present_entityId && that_present_entityId))
          return false;
        if (!this.entityId.equals(that.entityId))
          return false;
      }

      boolean this_present_groupList = true && this.isSetGroupList();
      boolean that_present_groupList = true && that.isSetGroupList();
      if (this_present_groupList || that_present_groupList) {
        if (!(this_present_groupList && that_present_groupList))
          return false;
        if (!this.groupList.equals(that.groupList))
          return false;
      }

      boolean this_present_perssionTypeId = true && this.isSetPerssionTypeId();
      boolean that_present_perssionTypeId = true && that.isSetPerssionTypeId();
      if (this_present_perssionTypeId || that_present_perssionTypeId) {
        if (!(this_present_perssionTypeId && that_present_perssionTypeId))
          return false;
        if (!this.perssionTypeId.equals(that.perssionTypeId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_entityId = true && (isSetEntityId());
      list.add(present_entityId);
      if (present_entityId)
        list.add(entityId);

      boolean present_groupList = true && (isSetGroupList());
      list.add(present_groupList);
      if (present_groupList)
        list.add(groupList);

      boolean present_perssionTypeId = true && (isSetPerssionTypeId());
      list.add(present_perssionTypeId);
      if (present_perssionTypeId)
        list.add(perssionTypeId);

      return list.hashCode();
    }

    @Override
    public int compareTo(revokeEntitySharingFromGroups_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetEntityId()).compareTo(other.isSetEntityId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityId, other.entityId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetGroupList()).compareTo(other.isSetGroupList());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetGroupList()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.groupList, other.groupList);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetPerssionTypeId()).compareTo(other.isSetPerssionTypeId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetPerssionTypeId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.perssionTypeId, other.perssionTypeId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("revokeEntitySharingFromGroups_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("entityId:");
      if (this.entityId == null) {
        sb.append("null");
      } else {
        sb.append(this.entityId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("groupList:");
      if (this.groupList == null) {
        sb.append("null");
      } else {
        sb.append(this.groupList);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("perssionTypeId:");
      if (this.perssionTypeId == null) {
        sb.append("null");
      } else {
        sb.append(this.perssionTypeId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (entityId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityId' was not present! Struct: " + toString());
      }
      if (groupList == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'groupList' was not present! Struct: " + toString());
      }
      if (perssionTypeId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'perssionTypeId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class revokeEntitySharingFromGroups_argsStandardSchemeFactory implements SchemeFactory {
      public revokeEntitySharingFromGroups_argsStandardScheme getScheme() {
        return new revokeEntitySharingFromGroups_argsStandardScheme();
      }
    }

    private static class revokeEntitySharingFromGroups_argsStandardScheme extends StandardScheme<revokeEntitySharingFromGroups_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, revokeEntitySharingFromGroups_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // ENTITY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.entityId = iprot.readString();
                struct.setEntityIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // GROUP_LIST
              if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
                {
                  org.apache.thrift.protocol.TList _list144 = iprot.readListBegin();
                  struct.groupList = new ArrayList<String>(_list144.size);
                  String _elem145;
                  for (int _i146 = 0; _i146 < _list144.size; ++_i146)
                  {
                    _elem145 = iprot.readString();
                    struct.groupList.add(_elem145);
                  }
                  iprot.readListEnd();
                }
                struct.setGroupListIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 4: // PERSSION_TYPE_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.perssionTypeId = iprot.readString();
                struct.setPerssionTypeIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, revokeEntitySharingFromGroups_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.entityId != null) {
          oprot.writeFieldBegin(ENTITY_ID_FIELD_DESC);
          oprot.writeString(struct.entityId);
          oprot.writeFieldEnd();
        }
        if (struct.groupList != null) {
          oprot.writeFieldBegin(GROUP_LIST_FIELD_DESC);
          {
            oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.groupList.size()));
            for (String _iter147 : struct.groupList)
            {
              oprot.writeString(_iter147);
            }
            oprot.writeListEnd();
          }
          oprot.writeFieldEnd();
        }
        if (struct.perssionTypeId != null) {
          oprot.writeFieldBegin(PERSSION_TYPE_ID_FIELD_DESC);
          oprot.writeString(struct.perssionTypeId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class revokeEntitySharingFromGroups_argsTupleSchemeFactory implements SchemeFactory {
      public revokeEntitySharingFromGroups_argsTupleScheme getScheme() {
        return new revokeEntitySharingFromGroups_argsTupleScheme();
      }
    }

    private static class revokeEntitySharingFromGroups_argsTupleScheme extends TupleScheme<revokeEntitySharingFromGroups_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, revokeEntitySharingFromGroups_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.entityId);
        {
          oprot.writeI32(struct.groupList.size());
          for (String _iter148 : struct.groupList)
          {
            oprot.writeString(_iter148);
          }
        }
        oprot.writeString(struct.perssionTypeId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, revokeEntitySharingFromGroups_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.entityId = iprot.readString();
        struct.setEntityIdIsSet(true);
        {
          org.apache.thrift.protocol.TList _list149 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
          struct.groupList = new ArrayList<String>(_list149.size);
          String _elem150;
          for (int _i151 = 0; _i151 < _list149.size; ++_i151)
          {
            _elem150 = iprot.readString();
            struct.groupList.add(_elem150);
          }
        }
        struct.setGroupListIsSet(true);
        struct.perssionTypeId = iprot.readString();
        struct.setPerssionTypeIdIsSet(true);
      }
    }

  }

  public static class revokeEntitySharingFromGroups_result implements org.apache.thrift.TBase<revokeEntitySharingFromGroups_result, revokeEntitySharingFromGroups_result._Fields>, java.io.Serializable, Cloneable, Comparable<revokeEntitySharingFromGroups_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("revokeEntitySharingFromGroups_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new revokeEntitySharingFromGroups_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new revokeEntitySharingFromGroups_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(revokeEntitySharingFromGroups_result.class, metaDataMap);
    }

    public revokeEntitySharingFromGroups_result() {
    }

    public revokeEntitySharingFromGroups_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public revokeEntitySharingFromGroups_result(revokeEntitySharingFromGroups_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public revokeEntitySharingFromGroups_result deepCopy() {
      return new revokeEntitySharingFromGroups_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public revokeEntitySharingFromGroups_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public revokeEntitySharingFromGroups_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof revokeEntitySharingFromGroups_result)
        return this.equals((revokeEntitySharingFromGroups_result)that);
      return false;
    }

    public boolean equals(revokeEntitySharingFromGroups_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(revokeEntitySharingFromGroups_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("revokeEntitySharingFromGroups_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class revokeEntitySharingFromGroups_resultStandardSchemeFactory implements SchemeFactory {
      public revokeEntitySharingFromGroups_resultStandardScheme getScheme() {
        return new revokeEntitySharingFromGroups_resultStandardScheme();
      }
    }

    private static class revokeEntitySharingFromGroups_resultStandardScheme extends StandardScheme<revokeEntitySharingFromGroups_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, revokeEntitySharingFromGroups_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, revokeEntitySharingFromGroups_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class revokeEntitySharingFromGroups_resultTupleSchemeFactory implements SchemeFactory {
      public revokeEntitySharingFromGroups_resultTupleScheme getScheme() {
        return new revokeEntitySharingFromGroups_resultTupleScheme();
      }
    }

    private static class revokeEntitySharingFromGroups_resultTupleScheme extends TupleScheme<revokeEntitySharingFromGroups_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, revokeEntitySharingFromGroups_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, revokeEntitySharingFromGroups_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

  public static class userHasAccess_args implements org.apache.thrift.TBase<userHasAccess_args, userHasAccess_args._Fields>, java.io.Serializable, Cloneable, Comparable<userHasAccess_args>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("userHasAccess_args");

    private static final org.apache.thrift.protocol.TField DOMAIN_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("domainId", org.apache.thrift.protocol.TType.STRING, (short)1);
    private static final org.apache.thrift.protocol.TField USER_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("userId", org.apache.thrift.protocol.TType.STRING, (short)2);
    private static final org.apache.thrift.protocol.TField ENTITY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("entityId", org.apache.thrift.protocol.TType.STRING, (short)3);
    private static final org.apache.thrift.protocol.TField PERMISSION_TYPE_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("permissionTypeId", org.apache.thrift.protocol.TType.STRING, (short)4);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new userHasAccess_argsStandardSchemeFactory());
      schemes.put(TupleScheme.class, new userHasAccess_argsTupleSchemeFactory());
    }

    public String domainId; // required
    public String userId; // required
    public String entityId; // required
    public String permissionTypeId; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      DOMAIN_ID((short)1, "domainId"),
      USER_ID((short)2, "userId"),
      ENTITY_ID((short)3, "entityId"),
      PERMISSION_TYPE_ID((short)4, "permissionTypeId");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 1: // DOMAIN_ID
            return DOMAIN_ID;
          case 2: // USER_ID
            return USER_ID;
          case 3: // ENTITY_ID
            return ENTITY_ID;
          case 4: // PERMISSION_TYPE_ID
            return PERMISSION_TYPE_ID;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.DOMAIN_ID, new org.apache.thrift.meta_data.FieldMetaData("domainId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.USER_ID, new org.apache.thrift.meta_data.FieldMetaData("userId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.ENTITY_ID, new org.apache.thrift.meta_data.FieldMetaData("entityId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      tmpMap.put(_Fields.PERMISSION_TYPE_ID, new org.apache.thrift.meta_data.FieldMetaData("permissionTypeId", org.apache.thrift.TFieldRequirementType.REQUIRED, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(userHasAccess_args.class, metaDataMap);
    }

    public userHasAccess_args() {
    }

    public userHasAccess_args(
      String domainId,
      String userId,
      String entityId,
      String permissionTypeId)
    {
      this();
      this.domainId = domainId;
      this.userId = userId;
      this.entityId = entityId;
      this.permissionTypeId = permissionTypeId;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public userHasAccess_args(userHasAccess_args other) {
      if (other.isSetDomainId()) {
        this.domainId = other.domainId;
      }
      if (other.isSetUserId()) {
        this.userId = other.userId;
      }
      if (other.isSetEntityId()) {
        this.entityId = other.entityId;
      }
      if (other.isSetPermissionTypeId()) {
        this.permissionTypeId = other.permissionTypeId;
      }
    }

    public userHasAccess_args deepCopy() {
      return new userHasAccess_args(this);
    }

    @Override
    public void clear() {
      this.domainId = null;
      this.userId = null;
      this.entityId = null;
      this.permissionTypeId = null;
    }

    public String getDomainId() {
      return this.domainId;
    }

    public userHasAccess_args setDomainId(String domainId) {
      this.domainId = domainId;
      return this;
    }

    public void unsetDomainId() {
      this.domainId = null;
    }

    /** Returns true if field domainId is set (has been assigned a value) and false otherwise */
    public boolean isSetDomainId() {
      return this.domainId != null;
    }

    public void setDomainIdIsSet(boolean value) {
      if (!value) {
        this.domainId = null;
      }
    }

    public String getUserId() {
      return this.userId;
    }

    public userHasAccess_args setUserId(String userId) {
      this.userId = userId;
      return this;
    }

    public void unsetUserId() {
      this.userId = null;
    }

    /** Returns true if field userId is set (has been assigned a value) and false otherwise */
    public boolean isSetUserId() {
      return this.userId != null;
    }

    public void setUserIdIsSet(boolean value) {
      if (!value) {
        this.userId = null;
      }
    }

    public String getEntityId() {
      return this.entityId;
    }

    public userHasAccess_args setEntityId(String entityId) {
      this.entityId = entityId;
      return this;
    }

    public void unsetEntityId() {
      this.entityId = null;
    }

    /** Returns true if field entityId is set (has been assigned a value) and false otherwise */
    public boolean isSetEntityId() {
      return this.entityId != null;
    }

    public void setEntityIdIsSet(boolean value) {
      if (!value) {
        this.entityId = null;
      }
    }

    public String getPermissionTypeId() {
      return this.permissionTypeId;
    }

    public userHasAccess_args setPermissionTypeId(String permissionTypeId) {
      this.permissionTypeId = permissionTypeId;
      return this;
    }

    public void unsetPermissionTypeId() {
      this.permissionTypeId = null;
    }

    /** Returns true if field permissionTypeId is set (has been assigned a value) and false otherwise */
    public boolean isSetPermissionTypeId() {
      return this.permissionTypeId != null;
    }

    public void setPermissionTypeIdIsSet(boolean value) {
      if (!value) {
        this.permissionTypeId = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case DOMAIN_ID:
        if (value == null) {
          unsetDomainId();
        } else {
          setDomainId((String)value);
        }
        break;

      case USER_ID:
        if (value == null) {
          unsetUserId();
        } else {
          setUserId((String)value);
        }
        break;

      case ENTITY_ID:
        if (value == null) {
          unsetEntityId();
        } else {
          setEntityId((String)value);
        }
        break;

      case PERMISSION_TYPE_ID:
        if (value == null) {
          unsetPermissionTypeId();
        } else {
          setPermissionTypeId((String)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case DOMAIN_ID:
        return getDomainId();

      case USER_ID:
        return getUserId();

      case ENTITY_ID:
        return getEntityId();

      case PERMISSION_TYPE_ID:
        return getPermissionTypeId();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case DOMAIN_ID:
        return isSetDomainId();
      case USER_ID:
        return isSetUserId();
      case ENTITY_ID:
        return isSetEntityId();
      case PERMISSION_TYPE_ID:
        return isSetPermissionTypeId();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof userHasAccess_args)
        return this.equals((userHasAccess_args)that);
      return false;
    }

    public boolean equals(userHasAccess_args that) {
      if (that == null)
        return false;

      boolean this_present_domainId = true && this.isSetDomainId();
      boolean that_present_domainId = true && that.isSetDomainId();
      if (this_present_domainId || that_present_domainId) {
        if (!(this_present_domainId && that_present_domainId))
          return false;
        if (!this.domainId.equals(that.domainId))
          return false;
      }

      boolean this_present_userId = true && this.isSetUserId();
      boolean that_present_userId = true && that.isSetUserId();
      if (this_present_userId || that_present_userId) {
        if (!(this_present_userId && that_present_userId))
          return false;
        if (!this.userId.equals(that.userId))
          return false;
      }

      boolean this_present_entityId = true && this.isSetEntityId();
      boolean that_present_entityId = true && that.isSetEntityId();
      if (this_present_entityId || that_present_entityId) {
        if (!(this_present_entityId && that_present_entityId))
          return false;
        if (!this.entityId.equals(that.entityId))
          return false;
      }

      boolean this_present_permissionTypeId = true && this.isSetPermissionTypeId();
      boolean that_present_permissionTypeId = true && that.isSetPermissionTypeId();
      if (this_present_permissionTypeId || that_present_permissionTypeId) {
        if (!(this_present_permissionTypeId && that_present_permissionTypeId))
          return false;
        if (!this.permissionTypeId.equals(that.permissionTypeId))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_domainId = true && (isSetDomainId());
      list.add(present_domainId);
      if (present_domainId)
        list.add(domainId);

      boolean present_userId = true && (isSetUserId());
      list.add(present_userId);
      if (present_userId)
        list.add(userId);

      boolean present_entityId = true && (isSetEntityId());
      list.add(present_entityId);
      if (present_entityId)
        list.add(entityId);

      boolean present_permissionTypeId = true && (isSetPermissionTypeId());
      list.add(present_permissionTypeId);
      if (present_permissionTypeId)
        list.add(permissionTypeId);

      return list.hashCode();
    }

    @Override
    public int compareTo(userHasAccess_args other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetDomainId()).compareTo(other.isSetDomainId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetDomainId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domainId, other.domainId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetUserId()).compareTo(other.isSetUserId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetUserId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.userId, other.userId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetEntityId()).compareTo(other.isSetEntityId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetEntityId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.entityId, other.entityId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetPermissionTypeId()).compareTo(other.isSetPermissionTypeId());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetPermissionTypeId()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.permissionTypeId, other.permissionTypeId);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("userHasAccess_args(");
      boolean first = true;

      sb.append("domainId:");
      if (this.domainId == null) {
        sb.append("null");
      } else {
        sb.append(this.domainId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("userId:");
      if (this.userId == null) {
        sb.append("null");
      } else {
        sb.append(this.userId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("entityId:");
      if (this.entityId == null) {
        sb.append("null");
      } else {
        sb.append(this.entityId);
      }
      first = false;
      if (!first) sb.append(", ");
      sb.append("permissionTypeId:");
      if (this.permissionTypeId == null) {
        sb.append("null");
      } else {
        sb.append(this.permissionTypeId);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      if (domainId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'domainId' was not present! Struct: " + toString());
      }
      if (userId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'userId' was not present! Struct: " + toString());
      }
      if (entityId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'entityId' was not present! Struct: " + toString());
      }
      if (permissionTypeId == null) {
        throw new org.apache.thrift.protocol.TProtocolException("Required field 'permissionTypeId' was not present! Struct: " + toString());
      }
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class userHasAccess_argsStandardSchemeFactory implements SchemeFactory {
      public userHasAccess_argsStandardScheme getScheme() {
        return new userHasAccess_argsStandardScheme();
      }
    }

    private static class userHasAccess_argsStandardScheme extends StandardScheme<userHasAccess_args> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, userHasAccess_args struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 1: // DOMAIN_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.domainId = iprot.readString();
                struct.setDomainIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 2: // USER_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.userId = iprot.readString();
                struct.setUserIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 3: // ENTITY_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.entityId = iprot.readString();
                struct.setEntityIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 4: // PERMISSION_TYPE_ID
              if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
                struct.permissionTypeId = iprot.readString();
                struct.setPermissionTypeIdIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, userHasAccess_args struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.domainId != null) {
          oprot.writeFieldBegin(DOMAIN_ID_FIELD_DESC);
          oprot.writeString(struct.domainId);
          oprot.writeFieldEnd();
        }
        if (struct.userId != null) {
          oprot.writeFieldBegin(USER_ID_FIELD_DESC);
          oprot.writeString(struct.userId);
          oprot.writeFieldEnd();
        }
        if (struct.entityId != null) {
          oprot.writeFieldBegin(ENTITY_ID_FIELD_DESC);
          oprot.writeString(struct.entityId);
          oprot.writeFieldEnd();
        }
        if (struct.permissionTypeId != null) {
          oprot.writeFieldBegin(PERMISSION_TYPE_ID_FIELD_DESC);
          oprot.writeString(struct.permissionTypeId);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class userHasAccess_argsTupleSchemeFactory implements SchemeFactory {
      public userHasAccess_argsTupleScheme getScheme() {
        return new userHasAccess_argsTupleScheme();
      }
    }

    private static class userHasAccess_argsTupleScheme extends TupleScheme<userHasAccess_args> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, userHasAccess_args struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        oprot.writeString(struct.domainId);
        oprot.writeString(struct.userId);
        oprot.writeString(struct.entityId);
        oprot.writeString(struct.permissionTypeId);
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, userHasAccess_args struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        struct.domainId = iprot.readString();
        struct.setDomainIdIsSet(true);
        struct.userId = iprot.readString();
        struct.setUserIdIsSet(true);
        struct.entityId = iprot.readString();
        struct.setEntityIdIsSet(true);
        struct.permissionTypeId = iprot.readString();
        struct.setPermissionTypeIdIsSet(true);
      }
    }

  }

  public static class userHasAccess_result implements org.apache.thrift.TBase<userHasAccess_result, userHasAccess_result._Fields>, java.io.Serializable, Cloneable, Comparable<userHasAccess_result>   {
    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("userHasAccess_result");

    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.BOOL, (short)0);
    private static final org.apache.thrift.protocol.TField SRE_FIELD_DESC = new org.apache.thrift.protocol.TField("sre", org.apache.thrift.protocol.TType.STRUCT, (short)1);

    private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
    static {
      schemes.put(StandardScheme.class, new userHasAccess_resultStandardSchemeFactory());
      schemes.put(TupleScheme.class, new userHasAccess_resultTupleSchemeFactory());
    }

    public boolean success; // required
    public org.apache.airavata.sharing.registry.models.SharingRegistryException sre; // required

    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
      SUCCESS((short)0, "success"),
      SRE((short)1, "sre");

      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

      static {
        for (_Fields field : EnumSet.allOf(_Fields.class)) {
          byName.put(field.getFieldName(), field);
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, or null if its not found.
       */
      public static _Fields findByThriftId(int fieldId) {
        switch(fieldId) {
          case 0: // SUCCESS
            return SUCCESS;
          case 1: // SRE
            return SRE;
          default:
            return null;
        }
      }

      /**
       * Find the _Fields constant that matches fieldId, throwing an exception
       * if it is not found.
       */
      public static _Fields findByThriftIdOrThrow(int fieldId) {
        _Fields fields = findByThriftId(fieldId);
        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
        return fields;
      }

      /**
       * Find the _Fields constant that matches name, or null if its not found.
       */
      public static _Fields findByName(String name) {
        return byName.get(name);
      }

      private final short _thriftId;
      private final String _fieldName;

      _Fields(short thriftId, String fieldName) {
        _thriftId = thriftId;
        _fieldName = fieldName;
      }

      public short getThriftFieldId() {
        return _thriftId;
      }

      public String getFieldName() {
        return _fieldName;
      }
    }

    // isset id assignments
    private static final int __SUCCESS_ISSET_ID = 0;
    private byte __isset_bitfield = 0;
    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
    static {
      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
      tmpMap.put(_Fields.SRE, new org.apache.thrift.meta_data.FieldMetaData("sre", org.apache.thrift.TFieldRequirementType.DEFAULT, 
          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRUCT)));
      metaDataMap = Collections.unmodifiableMap(tmpMap);
      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(userHasAccess_result.class, metaDataMap);
    }

    public userHasAccess_result() {
    }

    public userHasAccess_result(
      boolean success,
      org.apache.airavata.sharing.registry.models.SharingRegistryException sre)
    {
      this();
      this.success = success;
      setSuccessIsSet(true);
      this.sre = sre;
    }

    /**
     * Performs a deep copy on <i>other</i>.
     */
    public userHasAccess_result(userHasAccess_result other) {
      __isset_bitfield = other.__isset_bitfield;
      this.success = other.success;
      if (other.isSetSre()) {
        this.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException(other.sre);
      }
    }

    public userHasAccess_result deepCopy() {
      return new userHasAccess_result(this);
    }

    @Override
    public void clear() {
      setSuccessIsSet(false);
      this.success = false;
      this.sre = null;
    }

    public boolean isSuccess() {
      return this.success;
    }

    public userHasAccess_result setSuccess(boolean success) {
      this.success = success;
      setSuccessIsSet(true);
      return this;
    }

    public void unsetSuccess() {
      __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    /** Returns true if field success is set (has been assigned a value) and false otherwise */
    public boolean isSetSuccess() {
      return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
    }

    public void setSuccessIsSet(boolean value) {
      __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
    }

    public org.apache.airavata.sharing.registry.models.SharingRegistryException getSre() {
      return this.sre;
    }

    public userHasAccess_result setSre(org.apache.airavata.sharing.registry.models.SharingRegistryException sre) {
      this.sre = sre;
      return this;
    }

    public void unsetSre() {
      this.sre = null;
    }

    /** Returns true if field sre is set (has been assigned a value) and false otherwise */
    public boolean isSetSre() {
      return this.sre != null;
    }

    public void setSreIsSet(boolean value) {
      if (!value) {
        this.sre = null;
      }
    }

    public void setFieldValue(_Fields field, Object value) {
      switch (field) {
      case SUCCESS:
        if (value == null) {
          unsetSuccess();
        } else {
          setSuccess((Boolean)value);
        }
        break;

      case SRE:
        if (value == null) {
          unsetSre();
        } else {
          setSre((org.apache.airavata.sharing.registry.models.SharingRegistryException)value);
        }
        break;

      }
    }

    public Object getFieldValue(_Fields field) {
      switch (field) {
      case SUCCESS:
        return isSuccess();

      case SRE:
        return getSre();

      }
      throw new IllegalStateException();
    }

    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
    public boolean isSet(_Fields field) {
      if (field == null) {
        throw new IllegalArgumentException();
      }

      switch (field) {
      case SUCCESS:
        return isSetSuccess();
      case SRE:
        return isSetSre();
      }
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object that) {
      if (that == null)
        return false;
      if (that instanceof userHasAccess_result)
        return this.equals((userHasAccess_result)that);
      return false;
    }

    public boolean equals(userHasAccess_result that) {
      if (that == null)
        return false;

      boolean this_present_success = true;
      boolean that_present_success = true;
      if (this_present_success || that_present_success) {
        if (!(this_present_success && that_present_success))
          return false;
        if (this.success != that.success)
          return false;
      }

      boolean this_present_sre = true && this.isSetSre();
      boolean that_present_sre = true && that.isSetSre();
      if (this_present_sre || that_present_sre) {
        if (!(this_present_sre && that_present_sre))
          return false;
        if (!this.sre.equals(that.sre))
          return false;
      }

      return true;
    }

    @Override
    public int hashCode() {
      List<Object> list = new ArrayList<Object>();

      boolean present_success = true;
      list.add(present_success);
      if (present_success)
        list.add(success);

      boolean present_sre = true && (isSetSre());
      list.add(present_sre);
      if (present_sre)
        list.add(sre);

      return list.hashCode();
    }

    @Override
    public int compareTo(userHasAccess_result other) {
      if (!getClass().equals(other.getClass())) {
        return getClass().getName().compareTo(other.getClass().getName());
      }

      int lastComparison = 0;

      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSuccess()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      lastComparison = Boolean.valueOf(isSetSre()).compareTo(other.isSetSre());
      if (lastComparison != 0) {
        return lastComparison;
      }
      if (isSetSre()) {
        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sre, other.sre);
        if (lastComparison != 0) {
          return lastComparison;
        }
      }
      return 0;
    }

    public _Fields fieldForId(int fieldId) {
      return _Fields.findByThriftId(fieldId);
    }

    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
      schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
    }

    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
      schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
      }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder("userHasAccess_result(");
      boolean first = true;

      sb.append("success:");
      sb.append(this.success);
      first = false;
      if (!first) sb.append(", ");
      sb.append("sre:");
      if (this.sre == null) {
        sb.append("null");
      } else {
        sb.append(this.sre);
      }
      first = false;
      sb.append(")");
      return sb.toString();
    }

    public void validate() throws org.apache.thrift.TException {
      // check for required fields
      // check for sub-struct validity
    }

    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
      try {
        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
      try {
        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
        __isset_bitfield = 0;
        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
      } catch (org.apache.thrift.TException te) {
        throw new java.io.IOException(te);
      }
    }

    private static class userHasAccess_resultStandardSchemeFactory implements SchemeFactory {
      public userHasAccess_resultStandardScheme getScheme() {
        return new userHasAccess_resultStandardScheme();
      }
    }

    private static class userHasAccess_resultStandardScheme extends StandardScheme<userHasAccess_result> {

      public void read(org.apache.thrift.protocol.TProtocol iprot, userHasAccess_result struct) throws org.apache.thrift.TException {
        org.apache.thrift.protocol.TField schemeField;
        iprot.readStructBegin();
        while (true)
        {
          schemeField = iprot.readFieldBegin();
          if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
            break;
          }
          switch (schemeField.id) {
            case 0: // SUCCESS
              if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
                struct.success = iprot.readBool();
                struct.setSuccessIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            case 1: // SRE
              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
                struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
                struct.sre.read(iprot);
                struct.setSreIsSet(true);
              } else { 
                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
              }
              break;
            default:
              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
          }
          iprot.readFieldEnd();
        }
        iprot.readStructEnd();

        // check for required fields of primitive type, which can't be checked in the validate method
        struct.validate();
      }

      public void write(org.apache.thrift.protocol.TProtocol oprot, userHasAccess_result struct) throws org.apache.thrift.TException {
        struct.validate();

        oprot.writeStructBegin(STRUCT_DESC);
        if (struct.isSetSuccess()) {
          oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
          oprot.writeBool(struct.success);
          oprot.writeFieldEnd();
        }
        if (struct.sre != null) {
          oprot.writeFieldBegin(SRE_FIELD_DESC);
          struct.sre.write(oprot);
          oprot.writeFieldEnd();
        }
        oprot.writeFieldStop();
        oprot.writeStructEnd();
      }

    }

    private static class userHasAccess_resultTupleSchemeFactory implements SchemeFactory {
      public userHasAccess_resultTupleScheme getScheme() {
        return new userHasAccess_resultTupleScheme();
      }
    }

    private static class userHasAccess_resultTupleScheme extends TupleScheme<userHasAccess_result> {

      @Override
      public void write(org.apache.thrift.protocol.TProtocol prot, userHasAccess_result struct) throws org.apache.thrift.TException {
        TTupleProtocol oprot = (TTupleProtocol) prot;
        BitSet optionals = new BitSet();
        if (struct.isSetSuccess()) {
          optionals.set(0);
        }
        if (struct.isSetSre()) {
          optionals.set(1);
        }
        oprot.writeBitSet(optionals, 2);
        if (struct.isSetSuccess()) {
          oprot.writeBool(struct.success);
        }
        if (struct.isSetSre()) {
          struct.sre.write(oprot);
        }
      }

      @Override
      public void read(org.apache.thrift.protocol.TProtocol prot, userHasAccess_result struct) throws org.apache.thrift.TException {
        TTupleProtocol iprot = (TTupleProtocol) prot;
        BitSet incoming = iprot.readBitSet(2);
        if (incoming.get(0)) {
          struct.success = iprot.readBool();
          struct.setSuccessIsSet(true);
        }
        if (incoming.get(1)) {
          struct.sre = new org.apache.airavata.sharing.registry.models.SharingRegistryException();
          struct.sre.read(iprot);
          struct.setSreIsSet(true);
        }
      }
    }

  }

}
