/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package cli_fmw.delegate.directory;
import cli_fmw.delegate.Delegate;
import cli_fmw.login.UserInfoAbstract;
import cli_fmw.utils.Selector;
import cli_fmw.main.ClipsException;
import cli_fmw.main.DirectoryItemNotFoundException;
import framework.beans.directory.DirectoryItemDetails;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import framework.security.MagicValues;
import framework.utils.ROList;
import java.util.HashMap;
/**
*
* @param <ITEMCLASS>
* @author axe
*/
public abstract class Directory<ITEMCLASS extends DirectoryItemRO<? extends DirectoryItemDetails>>
extends Delegate{
protected ArrayList<ITEMCLASS> idxItems = new ArrayList<ITEMCLASS>();
protected ArrayList<ITEMCLASS> sortedItems = new ArrayList<ITEMCLASS>();
protected IdComparator idComparator = new IdComparator();
private HashMap<String, ITEMCLASS> titleMap;
protected Directory() throws ClipsException {
}
protected final class IdComparator implements java.util.Comparator<ITEMCLASS> {
@Override
public int compare(ITEMCLASS o1, ITEMCLASS o2) {
return o1.getID() - o2.getID();
}
}
protected ITEMCLASS addToIDX2(ITEMCLASS item){
int idx = Collections.binarySearch(idxItems, item, idComparator);
if (idx < 0) {
idxItems.add((-idx) - 1, item);
return null;
}
else{
ITEMCLASS oldItem = idxItems.get(idx);
idxItems.set(idx, item);
return oldItem;
}
}
protected void removeFromIDX(ITEMCLASS item){
int idx = Collections.binarySearch(idxItems, item, idComparator);
if (idx >= 0) {
idxItems.remove(idx);
}
}
protected ITEMCLASS findIDX(int id){
return findById(idxItems, id);
}
protected ITEMCLASS findById(ArrayList<ITEMCLASS> idxItems, int id){
int start = 0, end = idxItems.size() - 1;
while (start <= end){
int midle = (start + end) >>> 1;
ITEMCLASS itm = idxItems.get(midle);
int cur = itm.getID();
if (cur < id){
start = midle + 1;
}
else if (cur > id){
end = midle - 1;
}
else {
return itm;
}
}
return null;
}
protected void fastAddLoadedItem(ITEMCLASS item) throws ClipsException{
UserInfoAbstract userinfo = UserInfoAbstract.get();
if(item.isVisible() || (userinfo != null && userinfo.canUseHiddenDirectoryItems())) {
sortedItems.add(item);
if (titleMap == null) {
titleMap = new HashMap<String, ITEMCLASS>();
}
titleMap.put(item.getTitle(), item);
}
}
protected void addLoadedItem(ITEMCLASS item) throws ClipsException {
ITEMCLASS oldItem = addToIDX2(item);
if (oldItem != null){
addToIDX2(oldItem);
throw new RuntimeException("Попытка дважды добавить элемент с одинаковым ID");
/*for (Iterator<ITEMCLASS> it = sortedItems.iterator(); it.hasNext();) {
if (it.next() == oldItem){
it.remove();
break;
}
}}*/
}
fastAddLoadedItem(item);
sort();
}
public boolean isItemLoaded(int id){
return findIDX(id) != null;
}
void setDirectoryIndex(ArrayList<ITEMCLASS> idxItems){
this.idxItems = idxItems;
}
protected void removeOrphanItem(ITEMCLASS item) throws ClipsException {
removeFromIDX(item);
sortedItems.remove(item);
}
public void setUnselectable(ITEMCLASS item) {
sortedItems.remove(item);
}
public abstract String getDirectoryTitle();
@SuppressWarnings("unchecked")
public ITEMCLASS getItemFromID(int id) throws DirectoryItemNotFoundException {
//знаю что изврат
if (id == MagicValues.ACCESS_DENIED_ID){
if (this instanceof AccessDeniable){
return (ITEMCLASS) ((AccessDeniable)this).getNotAccessItem();
}else{
throw new DirectoryItemNotFoundException("Элемент запрещённого доступа для справочника \'"
+ getDirectoryTitle() + "\' не определён");
}
}
ITEMCLASS directoryItem = findIDX(id);
if (directoryItem != null) {
return directoryItem;
} else if (this instanceof DirectoryRecursive) {
return null;
} else {
throw new DirectoryItemNotFoundException("Элемент справочника \'" + getDirectoryTitle() + "\' № " + id + " не найден");
}
}
private HashMap<String, ITEMCLASS> getTitleMap(Directory<ITEMCLASS> dir) {
HashMap<String, ITEMCLASS> map = new HashMap<String, ITEMCLASS>();
Selector<ITEMCLASS> items = dir.getItems();
for (int i = 0; i < items.size(); i++) {
ITEMCLASS item = items.get(i);
map.put(item.getTitle(), item);
}
return map;
}
public ITEMCLASS getItemFromTitle(String title) throws DirectoryItemNotFoundException {
if (titleMap == null) {
titleMap = getTitleMap(this);
}
return titleMap.get(title);
}
public ITEMCLASS getNullItem() {
try {
return getItemFromID(0);
} catch (ClipsException ex) {
//nullitem либо есть либо нет никакого эксепшена
return null;
}
}
public ITEMCLASS isInDirectory(String s) {
for (int i = 0; i < sortedItems.size(); i++) {
if (s.equals(sortedItems.get(i).getTitle())) {
return sortedItems.get(i);
}
}
return null;
}
protected abstract void load() throws ClipsException;
public void sort() throws ClipsException {
if (sortedItems != null) {
Collections.sort(sortedItems);
}
}
/**
* Возвращает список итемов, кторые могут быть выбранными (Selectable)
* @return
*/
public Selector<ITEMCLASS> getItems() /*throws DirectoryItemNotFoundException */{
return new ItemSelector();
}
protected class ItemSelector implements Selector<ITEMCLASS> {
@Override
public int size() {
return sortedItems.size();
}
@Override
public ITEMCLASS get(int index) {
if (index >= size()) {
throw new IndexOutOfBoundsException("Index is out of range:" + index);
}
return sortedItems.get(index);
}
}
public ROList<ITEMCLASS> getItemsList(){
return new ROList<ITEMCLASS>(sortedItems);
}
public ITEMCLASS[] toArray(ITEMCLASS[] array) throws ClipsException{
return sortedItems.toArray(array);
}
public ITEMCLASS[] toArray(ITEMCLASS[] array, boolean withNull) throws ClipsException{
List<ITEMCLASS> visible = new LinkedList<ITEMCLASS>(sortedItems);
Iterator<ITEMCLASS> it = visible.iterator();
while(it.hasNext()) {
ITEMCLASS item = it.next();
if(!withNull && item.getID() == 0) {
it.remove();
}
}
return visible.toArray(array);
}
public DirectoryItemRO[] toArray() throws ClipsException {
DirectoryItemRO[] array = new DirectoryItemRO[sortedItems.size()];
return sortedItems.toArray(array);
}
public DirectoryItemRO[] toArray(boolean withNull) throws ClipsException {
List<ITEMCLASS> visible = new LinkedList<ITEMCLASS>(sortedItems);
Iterator<ITEMCLASS> it = visible.iterator();
while(it.hasNext()) {
ITEMCLASS item = it.next();
if(!withNull && item.getID() == 0) {
it.remove();
}
}
DirectoryItemRO[] array = new DirectoryItemRO[visible.size()];
return visible.toArray(array);
}
}