class SyncLocalOccupantsAndSendJoinPresenceTask implements ClusterTask<Void>
{
    private static final Logger Log = LoggerFactory.getLogger(SyncLocalOccupantsAndSendJoinPresenceTask.class);

    private String subdomain;
    private Set<OccupantManager.Occupant> occupants = new HashSet<>();
    private NodeID originator;

    public SyncLocalOccupantsAndSendJoinPresenceTask() {}

    public SyncLocalOccupantsAndSendJoinPresenceTask(@Nonnull final String subdomain, @Nonnull final Set<OccupantManager.Occupant> occupants) {
        this.subdomain = subdomain;
        this.occupants = occupants;
        this.originator = XMPPServer.getInstance().getNodeID();
    }

    public Set<OccupantManager.Occupant> getOccupants() {
        return occupants;
    }

    public NodeID getOriginator() {
        return originator;
    }

    @Override
    public Void getResult() {
        return null;
    }

    @Override
    public void run() {
        Log.debug("Going to execute sync occupants task for {} occupants from node {}", occupants.size(), originator);
        final MultiUserChatService multiUserChatService = XMPPServer.getInstance().getMultiUserChatManager().getMultiUserChatService(subdomain);
        ((MultiUserChatServiceImpl) multiUserChatService).process(this);
        Log.trace("Finished executing sync occupants task for occupants {} from node {}", occupants.size(), originator);
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException
    {
        final ExternalizableUtil externalizableUtil = ExternalizableUtil.getInstance();
        externalizableUtil.writeSafeUTF(out, subdomain);
        externalizableUtil.writeLong(out, occupants.size());
        for (final OccupantManager.Occupant occupant : occupants) {
            externalizableUtil.writeSafeUTF(out, occupant.getRoomName());
            externalizableUtil.writeSafeUTF(out, occupant.getNickname());
            externalizableUtil.writeSerializable(out, occupant.getRealJID());
            // We should not send the lastActive field, as that's used only by the cluster node that the occupant is local to.
        }
        externalizableUtil.writeSerializable(out, originator);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
    {<FILL_FUNCTION_BODY>}
}

        final ExternalizableUtil externalizableUtil = ExternalizableUtil.getInstance();
        subdomain = externalizableUtil.readSafeUTF(in);
        final long size = externalizableUtil.readLong(in);
        this.occupants = new HashSet<>();
        for (long i=0; i<size; i++) {
            final String roomName = externalizableUtil.readSafeUTF(in);
            final String nickname = externalizableUtil.readSafeUTF(in);
            final JID realJID = (JID) externalizableUtil.readSerializable(in);
            final OccupantManager.Occupant occupant = new OccupantManager.Occupant(roomName, nickname, realJID);
            occupants.add(occupant);
        }
        originator = (NodeID) externalizableUtil.readSerializable(in);
    
<no_super_class>