/* * The MIT License (MIT) * * Copyright (c) 2013 AlgorithmX2 * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package appeng.api.storage; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; import appeng.api.config.AccessRestriction; import appeng.api.config.Actionable; import appeng.api.networking.security.BaseActionSource; import appeng.api.storage.data.IAEStack; import appeng.api.storage.data.IItemList; import com.google.common.collect.ImmutableList; /** * Common implementation of a simple class that monitors injection/extraction of a inventory to send events to a list of * listeners. * * @param */ public class MEMonitorHandler implements IMEMonitor { private final IMEInventoryHandler internalHandler; private final IItemList cachedList; private final HashMap, Object> listeners = new HashMap, Object>(); protected boolean hasChanged = true; public MEMonitorHandler( IMEInventoryHandler t ) { this.internalHandler = t; this.cachedList = t.getChannel().createList(); } public MEMonitorHandler( IMEInventoryHandler t, StorageChannel chan ) { this.internalHandler = t; this.cachedList = chan.createList(); } @Override public void addListener( IMEMonitorHandlerReceiver l, Object verificationToken ) { this.listeners.put( l, verificationToken ); } @Override public void removeListener( IMEMonitorHandlerReceiver l ) { this.listeners.remove( l ); } @Override public StackType injectItems( StackType input, Actionable mode, BaseActionSource src ) { if( mode == Actionable.SIMULATE ) { return this.getHandler().injectItems( input, mode, src ); } return this.monitorDifference( input.copy(), this.getHandler().injectItems( input, mode, src ), false, src ); } protected IMEInventoryHandler getHandler() { return this.internalHandler; } private StackType monitorDifference( IAEStack original, StackType leftOvers, boolean extraction, BaseActionSource src ) { StackType diff = (StackType) original.copy(); if( extraction ) { diff.setStackSize( leftOvers == null ? 0 : -leftOvers.getStackSize() ); } else if( leftOvers != null ) { diff.decStackSize( leftOvers.getStackSize() ); } if( diff.getStackSize() != 0 ) { this.postChangesToListeners( ImmutableList.of( diff ), src ); } return leftOvers; } protected void postChangesToListeners( Iterable changes, BaseActionSource src ) { this.notifyListenersOfChange( changes, src ); } protected void notifyListenersOfChange( Iterable diff, BaseActionSource src ) { this.hasChanged = true;// need to update the cache. Iterator, Object>> i = this.getListeners(); while( i.hasNext() ) { Entry, Object> o = i.next(); IMEMonitorHandlerReceiver receiver = o.getKey(); if( receiver.isValid( o.getValue() ) ) { receiver.postChange( this, diff, src ); } else { i.remove(); } } } protected Iterator, Object>> getListeners() { return this.listeners.entrySet().iterator(); } @Override public StackType extractItems( StackType request, Actionable mode, BaseActionSource src ) { if( mode == Actionable.SIMULATE ) { return this.getHandler().extractItems( request, mode, src ); } return this.monitorDifference( request.copy(), this.getHandler().extractItems( request, mode, src ), true, src ); } @Override public StorageChannel getChannel() { return this.getHandler().getChannel(); } @Override public AccessRestriction getAccess() { return this.getHandler().getAccess(); } @Override public IItemList getStorageList() { if( this.hasChanged ) { this.hasChanged = false; this.cachedList.resetStatus(); return this.getAvailableItems( this.cachedList ); } return this.cachedList; } @Override public boolean isPrioritized( StackType input ) { return this.getHandler().isPrioritized( input ); } @Override public boolean canAccept( StackType input ) { return this.getHandler().canAccept( input ); } @Override public IItemList getAvailableItems( IItemList out ) { return this.getHandler().getAvailableItems( out ); } @Override public int getPriority() { return this.getHandler().getPriority(); } @Override public int getSlot() { return this.getHandler().getSlot(); } @Override public boolean validForPass( int i ) { return this.getHandler().validForPass( i ); } }