/*
* Created on Aug 18, 2003
*
*/
package se.idega.idegaweb.commune.accounting.userinfo.business;
import is.idega.block.family.business.FamilyLogic;
import is.idega.block.family.business.NoChildrenFound;
import is.idega.block.family.business.NoCohabitantFound;
import is.idega.block.family.business.NoCustodianFound;
import is.idega.block.family.business.NoSpouseFound;
import java.rmi.RemoteException;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;
import java.util.Vector;
import javax.ejb.CreateException;
import javax.ejb.FinderException;
import se.idega.idegaweb.commune.accounting.userinfo.data.BruttoIncome;
import se.idega.idegaweb.commune.accounting.userinfo.data.BruttoIncomeHome;
import se.idega.idegaweb.commune.accounting.userinfo.data.HouseHoldFamily;
import se.idega.idegaweb.commune.accounting.userinfo.data.InvoiceReceiver;
import se.idega.idegaweb.commune.accounting.userinfo.data.InvoiceReceiverHome;
import se.idega.idegaweb.commune.accounting.userinfo.data.SortableSibling;
import se.idega.idegaweb.commune.business.CommuneUserBusiness;
import se.idega.idegaweb.commune.care.data.ChildCareContract;
import se.idega.idegaweb.commune.care.data.ChildCareContractHome;
import com.idega.business.IBOLookup;
import com.idega.business.IBOServiceBean;
import com.idega.core.location.data.Address;
import com.idega.data.IDOStoreException;
import com.idega.user.business.UserBusiness;
import com.idega.user.data.User;
import com.idega.util.TimePeriod;
/**
* UserInfoServiceBean
* @author aron
* @version 1.0
*/
public class UserInfoServiceBean extends IBOServiceBean implements UserInfoService {
public BruttoIncome createBruttoIncome(Integer userID,Float income, Date validFrom,Integer creatorID) throws RemoteException{
BruttoIncome bruttoIncome = null;
try {
bruttoIncome = getBruttoIncomeHome().create();
bruttoIncome.setIncome(income);
bruttoIncome.setValidFrom((java.sql.Date)validFrom);
bruttoIncome.setUser(userID);
if (creatorID != null) {
bruttoIncome.setCreator(creatorID);
}
bruttoIncome.setCreated(new Timestamp(System.currentTimeMillis()));
bruttoIncome.store();
}
catch (IDOStoreException e) {
e.printStackTrace();
}
catch (CreateException e) {
e.printStackTrace();
}
return bruttoIncome;
}
public BruttoIncomeHome getBruttoIncomeHome() throws RemoteException{
return (BruttoIncomeHome) getIDOHome(BruttoIncome.class);
}
/**
* Sets the specified user as invoice receiver.
* @param user the user to set as invoice receiver
* @author Anders Lindman
*/
public InvoiceReceiver createInvoiceReceiver(User user) {
InvoiceReceiver ir = null;
try {
InvoiceReceiverHome home = getInvoiceReceiverHome();
try {
ir = home.findByPrimaryKey(user.getPrimaryKey());
} catch (FinderException e) {
ir = home.create();
ir.setUser(user);
}
ir.setIsReceiver(true);
ir.store();
} catch (Exception e) {}
return ir;
}
/**
* @author Anders Lindman
*/
public InvoiceReceiverHome getInvoiceReceiverHome() throws RemoteException {
return (InvoiceReceiverHome) getIDOHome(InvoiceReceiver.class);
}
public ChildCareContractHome getChildCareContractHome() throws RemoteException {
return (ChildCareContractHome) getIDOHome(ChildCareContract.class);
}
/**
* Returns true if the user with the specified id is an invoice receiver.
* @author Anders Lindman
*/
public boolean isInvoiceReceiver(int userId) {
boolean isReceiver = false;
try {
InvoiceReceiver ir = getInvoiceReceiverHome().findByUser(userId);
isReceiver = ir.getIsReceiver();
} catch (Exception e) {}
return isReceiver;
}
/**
* Returns true if the specified user is an invoice receiver.
* @author Anders Lindman
*/
public boolean isInvoiceReceiver(User user) {
int userId = -1;
try {
userId = ((Integer) user.getPrimaryKey()).intValue();
} catch (Exception e) {}
return isInvoiceReceiver(userId);
}
/**
* Returns a HouseHoldFamily created from head of family
* @param headOfFamilly
* @return
*/
public HouseHoldFamily getHouseHoldFamily(User head)throws RemoteException{
if(head!=null){
CommuneUserBusiness userService = (CommuneUserBusiness) getServiceInstance(CommuneUserBusiness.class);
FamilyLogic familyService = userService.getMemberFamilyLogic();
User spouse = null;
try {
spouse = familyService.getSpouseFor(head);
}
catch (NoSpouseFound e) {
}
catch (RemoteException e) {
e.printStackTrace();
}
User cohabitant = null;
try {
cohabitant = familyService.getCohabitantFor(head);
}
catch (NoCohabitantFound e1) {
}
catch (RemoteException e1) {
e1.printStackTrace();
}
Collection parentialChildren= null;
try {
parentialChildren = familyService.getChildrenFor(head);
}
catch (NoChildrenFound e2) {
}
catch (RemoteException e2) {
e2.printStackTrace();
}
Collection custodyChildren= null;
try {
custodyChildren = familyService.getChildrenInCustodyOf(head);
}
catch (NoChildrenFound e3) {
}
catch (RemoteException e3) {
e3.printStackTrace();
}
Address address = userService.getUserAddress1(((Integer)head.getPrimaryKey()).intValue());
HouseHoldFamily family = new HouseHoldFamily(head);
Address addr;
if(address!=null){
family.setAddress(address);
if(spouse!=null){
addr = userService.getUserAddress1(((Integer)spouse.getPrimaryKey()).intValue());
if(isEqual(address,addr)){
family.setSpouse(spouse);
}
}
if(cohabitant!=null){
// is spouse the same person as cohabitant
//if(spouse!=null && !spouse.getPrimaryKey().toString().equals(cohabitant.getPrimaryKey().toString()) ){
addr = userService.getUserAddress1(((Integer)cohabitant.getPrimaryKey()).intValue());
if(isEqual(address,addr))
family.setCohabitant(cohabitant);
//}
}
if(parentialChildren!=null && !parentialChildren.isEmpty()){
Collection childs = new Vector(parentialChildren.size());
for (Iterator iter = parentialChildren.iterator(); iter.hasNext();) {
User child = (User) iter.next();
addr = userService.getUserAddress1(((Integer)child.getPrimaryKey()).intValue());
if(isEqual(address,addr)){
childs.add(child);
}
}
if(!childs.isEmpty())
family.setParentialChildren(childs);
}
if(custodyChildren!=null && !custodyChildren.isEmpty()){
Collection childs = new Vector(custodyChildren.size());
for (Iterator iter = custodyChildren.iterator(); iter.hasNext();) {
User child = (User) iter.next();
addr = userService.getUserAddress1(((Integer)child.getPrimaryKey()).intValue());
if(isEqual(address,addr)){
childs.add(child);
}
}
if(!childs.isEmpty())
family.setCustodyChildren(childs);
}
}
return family;
}
return null;
}
/**
* Returns the sibling order according to Check & Peng rules.
* Most importantly, it only involves children i pre-school
*/
public int getSiblingOrder(User child, TimePeriod period) throws RemoteException, SiblingOrderException {
return getSiblingOrder (child, new HashMap (), period);
}
private boolean hasValidContract
(final User child, final TimePeriod period) throws RemoteException {
try {
getChildCareContractHome ().findContractByChildAndPeriod (child, period);
return true;
} catch (FinderException e) {
return false;
}
}
/**
* Returns the sibling order according to Check & Peng rules.
* Most importantly, it only involves children i pre-school
*/
public int getSiblingOrder(User child, Map siblingOrders, TimePeriod period) throws RemoteException, SiblingOrderException {
UserBusiness userBus = (UserBusiness) IBOLookup.getServiceInstance(getIWApplicationContext(), UserBusiness.class);
//First see if the child already has been given a sibling order
Integer order = (Integer)siblingOrders.get(child.getPrimaryKey());
if(order != null)
{
return order.intValue(); //Sibling order already calculated.
}
if (!hasValidContract (child, period)) {
throw new SiblingOrderException (child.getName() + " has no contract");
}
TreeSet sortedSiblings = new TreeSet(); //Container for the siblings that keeps them in sorted order
Address childAddress = userBus.getUsersMainAddress(child);
if (null == childAddress) {
throw new SiblingOrderException (child.getPersonalID() + " " + child.getName () + " has no Address");
}
//Add the child to the sibbling collection right away to make sure it will be in there
//This should really happen in the main loop below as well, but this is done since
//the realtionships seem to be a bit unreliable
sortedSiblings.add(new SortableSibling(child));
Collection adults;
try {
adults = getCustodiansAndTheirPartners(child);
} catch (NoCustodianFound e1) {
throw new SiblingOrderException("No custodians found for the child.");
}
//Loop through all adults
Iterator adultIter = adults.iterator();
while(adultIter.hasNext()){
User adult = (User)adultIter.next();
Iterator siblingsIter;
try {
siblingsIter = getMemberFamilyLogic ().getChildrenInCustodyOf (adult).iterator();
//Itterate through their kids
while(siblingsIter.hasNext())
{
User sibling = (User) siblingsIter.next();
try {
Address siblingAddress = userBus.getUsersMainAddress(sibling);
if (hasValidContract (sibling, period)
&& isEqual (childAddress, siblingAddress)) {
SortableSibling sortableSibling = new SortableSibling(sibling);
if(!sortedSiblings.contains(sortableSibling)){
sortedSiblings.add(sortableSibling);
}
}
} catch (NullPointerException e) {
e.printStackTrace ();
String childName = child.getPersonalID() + " " + child.getName () + (child.getPrimaryKey ().equals (sibling.getPrimaryKey ()) ? "" : " or " + sibling.getPersonalID() + " " + sibling.getName ());
throw new SiblingOrderException (childName + " probably has missing fields in address", e);
}
}
} catch (NoChildrenFound e) {
// no problem, all related adults dont have children, iterate to next
} catch (RemoteException e2) {
e2.printStackTrace();
throw new SiblingOrderException (child.getName() + " invoice.DBError");
}
}
//Store the sorting order
Iterator sortedIter = sortedSiblings.iterator();
int orderNr = 1;
while(sortedIter.hasNext()){
SortableSibling sortableSibling = (SortableSibling)sortedIter.next();
siblingOrders.put(sortableSibling.getSibling().getPrimaryKey(),new Integer(orderNr));
// log("Added child "+sortableSibling.getSibling()+" as sibling "+orderNr+" out of "+sortedSiblings.size());
orderNr++;
}
//Look up the order of the child that started the whole thing
order = (Integer)siblingOrders.get(child.getPrimaryKey());
if(order != null)
{
return order.intValue();
}
//This should really never happen
throw new SiblingOrderException("Could not find the sibling order.");
}
public Collection getCustodiansAndTheirPartners(User child) throws RemoteException, NoCustodianFound {
//Gather up a collection of the parents and their cohabitants
Collection parents = getMemberFamilyLogic ().getCustodiansFor(child);
//Adults hold all the adults that could be living on the same address
Collection adults = new HashSet(parents);
Iterator parentIter = parents.iterator();
//Itterate through parents
while(parentIter.hasNext()){
User parent = (User)parentIter.next();
try {
adults.add(getMemberFamilyLogic ().getCohabitantFor(parent));
} catch (NoCohabitantFound e) {
// no problem, custodian don't need to have cohabitant
}
try {
adults.add(getMemberFamilyLogic ().getSpouseFor(parent));
} catch (NoSpouseFound e) {
// no problem, custodian don't need to have spouse
}
}
return adults;
}
public Collection getCustodiansAndTheirPartnersAtSameAddress(User child) throws RemoteException, NoCustodianFound {
Collection adults = getCustodiansAndTheirPartners (child);
Collection result = new HashSet ();
final Address childAddress = getUserBusiness ().getUsersMainAddress (child);
for (Iterator i = adults.iterator (); i.hasNext ();) {
final User adult = (User) i.next ();
final Address adultAddress
= getUserBusiness ().getUsersMainAddress(adult);
if (null != childAddress && null != adultAddress
&& isEqual (childAddress, adultAddress)) {
result.add (adult);
}
}
return result;
}
/**
* Compares two addresses on street name, the number part of street number,
* postal code and country. Address.isEqualTo compares the whole number part,
* including nb, 1tr etc., which isn't sufficiant here. This a formal request
* from the customer.
*/
private static boolean isEqual (final Address address1,
final Address address2) {
// In order to make this method as fast as possible...
// - retreive fields lazy - return as soon as differ is known
// - compare what's expected to be most differing field first
// - fields joined from other tables with foreign keys are considered late
try {
// if this is the same address row, then return immediately
if(null == address1 || null == address2){
return false;
}
if (address1.getPrimaryKey ().equals (address2.getPrimaryKey ())) {
return true;
}
if(null == address1.getStreetName() || null == address2.getStreetName()){
return false;
}
String name1 = address1.getStreetName().trim();
String name2 = address2.getStreetName().trim();
if (name1.equalsIgnoreCase(name2)) {
// they have same street name
String number1 = address1.getStreetNumber().trim();
String number2 = address2.getStreetNumber().trim();
if (startingNumberPart (number1).equalsIgnoreCase (startingNumberPart (number2))) {
// they have same starting number
if ((null != address1.getPostalCode() && null != address2.getPostalCode ()) &&
address1.getPostalCode ().equals (address2.getPostalCode ())) {
// they have same postal code
if (address1.getCountryId () == address2.getCountryId ()) {
// they have same country id
return true;
}
}
}
}
return false;
} catch (Exception e) {
return false;
}
}
private static String startingNumberPart (final String string) {
return (string != null ? string : "").trim ().split ("\\D", 2) [0];
}
protected UserBusiness getUserBusiness() throws RemoteException {
return (UserBusiness) getServiceInstance(UserBusiness.class);
}
protected FamilyLogic getMemberFamilyLogic() throws RemoteException {
return (FamilyLogic) getServiceInstance(FamilyLogic.class);
}
}