Package org.rioproject.examples.hospital.service

Source Code of org.rioproject.examples.hospital.service.HospitalImpl$DoctorComparator

/*
* Copyright to the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.rioproject.examples.hospital.service;

import org.rioproject.associations.Association;
import org.rioproject.associations.AssociationServiceListener;
import org.rioproject.servicebean.ServiceBeanContext;
import org.rioproject.examples.hospital.*;
import org.rioproject.examples.hospital.Doctor.Status;
import org.rioproject.impl.watch.CounterWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
* Implementation of a {@link Hospital}
*/
public class HospitalImpl implements Hospital {
    private Iterable<Doctor> doctors;
    private Iterable<Bed> beds;
    private CounterWatch availableBeds;
    private ServiceBeanContext context;
    private final List<Patient> waitingRoom = new ArrayList<Patient>();
    private final static Logger logger = LoggerFactory.getLogger(HospitalImpl.class.getName());

    @SuppressWarnings("unused") /* Injection point for Rio */
    public void setServiceBeanContext(final ServiceBeanContext context) {
        this.context = context;
        availableBeds = new CounterWatch("availableBeds");
        context.getWatchRegistry().register(availableBeds);
    }

    @PostConstruct
    @SuppressWarnings("unused") /* Injection point for Rio */
    public void started() {
        Association<Bed> association = context.getAssociationManagement().getAssociation(Bed.class,
                                                                                         "Beds",
                                                                                         "Hospital");
        association.registerAssociationServiceListener(new AssociationServiceListener<Bed>() {

            public void serviceAdded(Bed b) {
                availableBeds.increment();
                synchronized(waitingRoom) {
                    if(waitingRoom.size()>0) {
                        Patient p = waitingRoom.get(0);
                        try {
                            doAdmitWithBed(p, b);
                            waitingRoom.remove(p);
                            logger.info("Removed {} from the waiting room, waiting room size is now: {}",
                                        p.getPatientInfo().getName(), waitingRoom.size());
                        } catch (AdmissionException e) {
                            logger.debug("Unable to assign patient {}", p.getPatientInfo().getName());
                        }
                    }
                }
            }

            public void serviceRemoved(Bed b) {
                availableBeds.decrement();
            }
        });
    }

    public Patient admit(final Patient p) throws AdmissionException {
        Bed bed = getEmptyBed();
        return doAdmitWithBed(p, bed);
    }

    public Patient release(final Patient p) throws AdmissionException {
        Patient released = null;
        try {
            Patient removedPatient = p.getBed().removePatient();
            if(removedPatient!=null) {
                availableBeds.increment();
                removedPatient.getDoctor().removePatient(removedPatient);
                released = removedPatient;
            }
        } catch (IOException e) {
            throw new AdmissionException(String.format("Patient %s could not be released", p.getPatientInfo().getName()),
                                         e);
        }
        return released;
    }

    private Patient doAdmitWithBed(final Patient p, final Bed bed) throws AdmissionException {
        if(bed==null) {
            addToWaitingRoom(p);
            throw new AdmissionException(String.format("No available beds for %s", p.getPatientInfo().getName()));
        }
        Doctor d = getAvailableDoctor();
        if(d==null) {
            addToWaitingRoom(p);
            throw new AdmissionException(String.format("No available Doctor for %s", p.getPatientInfo().getName()));
        }
        p.setDoctor(d);
        try {
            d.assignPatient(p);
        } catch(IOException e) {
            p.setDoctor(null);
            throw new AdmissionException("Could not get the patient a doctor", e);
        }
        try {
            p.setBed(bed);
            bed.setPatient(p);
        } catch(IOException e) {
            p.setDoctor(null);
            throw new AdmissionException("Could not get the patient into a bed", e);
        }
        availableBeds.decrement();
        return p;
    }

    private Doctor getAvailableDoctor() {
        Doctor d = null;
        List<Doctor> onDuty = get(Status.ON_DUTY, false);
        if(onDuty.size()>0) {
            if(onDuty.size()>1)
                Collections.sort(onDuty, new DoctorComparator());
            d = onDuty.get(0);
        }
        return d;
    }

    private Bed getEmptyBed() {
        Bed bed = null;
        for(Bed b : beds) {
            try {
                if(b.getPatient()==null) {
                    bed = b;
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return bed;
    }

    public List<Bed> getBeds() {
        List<Bed> bs = new ArrayList<Bed>();
        for(Bed b : beds)
            bs.add(b);
        return Collections.unmodifiableList(bs);
    }

    @SuppressWarnings("unused") /* Injection point for Rio */
    public void setDoctors(final Iterable<Doctor> drs) {
        doctors = drs;
    }

    @SuppressWarnings("unused") /* Injection point for Rio */
    public void setBeds(final Iterable<Bed> bs) {
        beds = bs;
    }

    public List<Doctor> getDoctors() {
        return get(null, true);
    }

    public List<Doctor> getDoctorsOnCall() {
        return get(Status.ON_CALL, true);
    }

    public List<Doctor> getDoctorsOnDuty() {
        return get(Status.ON_DUTY, true);
    }

    public List<Patient> getWaitingRoom() {
        return getWaitingRoomList();
    }

    private void addToWaitingRoom(final Patient p) {
        synchronized(waitingRoom) {
            if(waitingRoom.add(p)) {
                logger.info("Added {} to the waiting room, waiting room size is now: {}",
                            p.getPatientInfo().getName(), waitingRoom.size());
            } else {
                logger.info("Did not add {} to the waiting room, must already be waiting", p.getPatientInfo().getName());
            }
        }
    }

    public List<Patient> getAdmittedPatients() {
        List<Patient> l = new ArrayList<Patient>();
        for(Bed b : getBeds()) {
            try {
                Patient p = b.getPatient();
                if(p!=null)
                    l.add(p);
            } catch (IOException e) {
                logger.warn("Could not get Patient from Bed", e);
            }
        }
        return Collections.unmodifiableList(l);
    }

    private List<Patient> getWaitingRoomList() {
        List<Patient> l = new ArrayList<Patient>();
        synchronized(waitingRoom) {
            l.addAll(waitingRoom);
        }
        return Collections.unmodifiableList(l);
    }

    private List<Doctor> get(final Status status, final boolean immutable) {
        List<Doctor> list = new ArrayList<Doctor>();
        for(Doctor d : doctors) {
            if(status==null) {
                list.add(d);
            } else {
                try {
                    if(d.getStatus().equals(status)) {
                        list.add(d);
                    }
                } catch (IOException e) {
                    logger.warn("Could not get Doctor's Status", e);
                }
            }
        }
        return immutable?Collections.unmodifiableList(list):list;
    }

    class DoctorComparator implements Comparator<Doctor> {

        public int compare(final Doctor dr1, final Doctor dr2) {
            int dr1Patients = getPatientCount(dr1);
            int dr2Patients = getPatientCount(dr2);
            if(dr1Patients==dr2Patients)
                return 0;
            return dr1Patients<dr2Patients?-1:1;
        }
       
        int getPatientCount(final Doctor d) {
            int count = 0;
            try {
                List<Patient> l = d.getPatients();
                count = l.size();
            } catch (IOException e) {
                logger.warn("Getting patient count from a Doctor", e);
                /* */
            }
            return count;
        }
    }
}
TOP

Related Classes of org.rioproject.examples.hospital.service.HospitalImpl$DoctorComparator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.