/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package clips.delegate.service.discount;
import beans.discount.DiscountBean;
import beans.discount.DiscountBeanRemote;
import clips.delegate.directory.complex.DirectoryDiscountLevel;
import clips.delegate.directory.complex.DirectoryDiscountLevelItem;
import cli_fmw.delegate.directory.complex.DirectoryLocator;
import cli_fmw.delegate.DelegateStandart;
import cli_fmw.main.ClipsException;
import beans.discount.entity.DiscountDetails;
import clips.delegate.directory.simple.discountCard.DirectoryDiscountCardTypeItem;
import clips.delegate.directory.simple.serviceClass.DirectoryServiceClass;
import clips.delegate.directory.simple.serviceClass.DirectoryServiceClassItem;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
/**
* Делегат, позволяющий назначить или получить дисконты, уровни дисконтов
* @author axe
*/
public class DiscountLocal extends DelegateStandart<DiscountBeanRemote> {
/** тип диcконтной карта => информация о скидке (услуга-уровень и соотв скидка) */
private HashMap<DirectoryDiscountCardTypeItem, CardDiscounts> details
= new HashMap<DirectoryDiscountCardTypeItem, CardDiscounts>();
public DiscountLocal() throws ClipsException {
super(DiscountBean.class.getSimpleName());
initBean();
}
/**
* Возвращает интерфейс для получения информации по дисконтам для данной
* дисконтной карты
* @param discountCardType
* @return
* @throws ClipsException
*/
public Discounts getDiscounts(DirectoryDiscountCardTypeItem discountCardType) throws ClipsException {
CardDiscounts discount = details.get(discountCardType);
if(discount == null) {
discount = loadDiscounts(discountCardType);
}
return discount;
}
private CardDiscounts loadDiscounts(DirectoryDiscountCardTypeItem discountCardType) throws ClipsException {
CardDiscounts discount = new CardDiscounts();
List<DiscountDetails> list;
try {
list = bean().getDetails(discountCardType.getID());
} catch (Exception ex) {
clearBean();
throw new ClipsException("Не удалось загрузить дисконты",ex);
}
DirectoryDiscountLevel directoryLevels = DirectoryLocator.getDirectory(DirectoryDiscountLevel.class, false);
DirectoryServiceClass directoryClasses = DirectoryLocator.getDirectory(DirectoryServiceClass.class);
for(int i=0; i<list.size(); i++) {
DiscountDetails d = list.get(i);
DirectoryDiscountLevelItem level = directoryLevels.getItemFromID(d.level);
DirectoryServiceClassItem cls = directoryClasses.getItemFromID(d.cls);
discount.setValue(level, cls, d.value);
}
discount.setLoaded();
details.put(discountCardType, discount);
return discount;
}
/**
* Сохраняет в базу данных
* @throws ClipsException
*/
@Override
public void save1() throws ClipsException {
Iterator<DirectoryDiscountCardTypeItem> keys = details.keySet().iterator();
while(keys.hasNext()) {
DirectoryDiscountCardTypeItem key = keys.next();
CardDiscounts cardDiscounts = details.get(key);
if(cardDiscounts.isDirty()) {
try {
List<DiscountDetails> list = cardDiscounts.toSave();
bean().update(key.getID(), list);
cardDiscounts.commit();
fireContentStateEvent();
} catch(Exception ex) {
clearBean();
throw new ClipsException("Не удалось сохранить дисконты для карты '"
+ key.getTitle() + "'",ex);
}
}
}
}
/**
* отмена изменений
*/
@Override
public void restore() {
Iterator<CardDiscounts> cards = details.values().iterator();
while(cards.hasNext()) {
CardDiscounts cardDiscounts = cards.next();
cardDiscounts.restore();
}
fireContentStateEvent();
}
/**
* Проверка, нуждается в сохранении или нет
* @return
*/
@Override
public boolean isDirty() {
Iterator<CardDiscounts> cards = details.values().iterator();
while(cards.hasNext()) {
CardDiscounts cardDiscounts = cards.next();
if(cardDiscounts.isDirty()) {
return true;
}
}
return false;
}
/** ///////////////////////////////////////////////////////////////////////////////
* Основной рабочий класс
*/
private class CardDiscounts implements Discounts {
/**
* discount level && service class MAP to value
*/
private HashMap<ServiceLevelKey, Value> values = new HashMap<ServiceLevelKey, Value>();
boolean loaded;
void setLoaded() {
loaded = true;
}
/**
* Класс ключа, в который группирует 2 значения в одно - discount level && service class
*/
private class ServiceLevelKey {
DirectoryServiceClassItem service;
DirectoryDiscountLevelItem level;
/**
* Создает новый ключ
* @param service - класс услуги
* @param level - уровень дисконта
*/
ServiceLevelKey(DirectoryServiceClassItem service, DirectoryDiscountLevelItem level) {
this.service = service;
this.level = level;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final DiscountLocal.CardDiscounts.ServiceLevelKey other = (DiscountLocal.CardDiscounts.ServiceLevelKey) obj;
if (this.service != other.service && (this.service == null || !this.service.equals(other.service))) {
return false;
}
if (this.level != other.level && (this.level == null || !this.level.equals(other.level))) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 10000 * (this.service != null ? this.service.hashCode() : 0);
hash = hash + (this.level != null ? this.level.hashCode() : 0);
return hash;
}
} /// КОНЕЦ класса кулюча
private class Value implements Cloneable {
int value;
int original;
@Override
protected Value clone() {
try {
return (Value) super.clone();
} catch(CloneNotSupportedException ex) {
ex.printStackTrace();
return null;
}
}
}
/**
* Возвращает значение дисконта для данного уровня дисконта и данного класса услуг
* @param discountLevel - уровень дисконта
* @param serviceClass - класс услуг
* @return целое значение в сотых долях процента (100 = 1%)
*/
@Override
public int getValue(DirectoryDiscountLevelItem discountLevel, DirectoryServiceClassItem serviceClass) {
ServiceLevelKey key = new ServiceLevelKey(serviceClass, discountLevel);
Value val = values.get(key);
if(val != null) {
return val.value;
}
return 0;
}
/**
* Назанчает значение дисконта для данного уровня дисконта и данного класса услуг
* @param discountLevel - уровень дисконта
* @param serviceClass - класс услуг
* @param value значение дисконта в сотых долях процента (100 = 1%)
*/
@Override
public void setValue(DirectoryDiscountLevelItem discountLevel, DirectoryServiceClassItem serviceClass, int value){
ServiceLevelKey key = new ServiceLevelKey(serviceClass, discountLevel);
Value val = values.get(key);
if(val == null) {
val = new Value();
val.original = loaded ? 0 : value;
val.value = value;
values.put(key, val);
} else {
val.value = value;
}
fireContentStateEvent();
}
public void commit() {
Iterator<Value> i = values.values().iterator();
while(i.hasNext()) {
Value value = i.next();
value.original = value.value;
}
}
public void restore() {
Iterator<Value> i = values.values().iterator();
while(i.hasNext()) {
Value value = i.next();
value.value = value.original;
}
}
public List<DiscountDetails> toSave() {
Iterator<ServiceLevelKey> i = values.keySet().iterator();
List<DiscountDetails> list = new ArrayList<DiscountDetails>();
while(i.hasNext()) {
ServiceLevelKey key = i.next();
Value v = values.get(key);
if(v.original != v.value) {
DiscountDetails d = new DiscountDetails();
d.cls = key.service.getID();
d.level = key.level.getID();
d.value = v.value;
list.add(d);
}
}
return list;
}
public boolean isDirty() {
Iterator<Value> i = values.values().iterator();
while(i.hasNext()) {
Value value = i.next();
if(value.value != value.original) {
return true;
}
}
return false;
}
} //END OF CardDiscounts
}