fr.ritaly.dungeonmaster.item.ItemManager.java Source code

Java tutorial

Introduction

Here is the source code for fr.ritaly.dungeonmaster.item.ItemManager.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 fr.ritaly.dungeonmaster.item;

import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.apache.commons.lang.Validate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import fr.ritaly.dungeonmaster.Sector;
import fr.ritaly.dungeonmaster.event.ItemEvent;
import fr.ritaly.dungeonmaster.event.ItemEventSource;
import fr.ritaly.dungeonmaster.event.ItemEventSupport;
import fr.ritaly.dungeonmaster.event.ItemListener;

/**
 * An object responsible for managing items picked / dropped.
 *
 * @author <a href="mailto:francois.ritaly@gmail.com">Francois RITALY</a>
 */
public class ItemManager implements ItemEventSource, HasItems<Sector> {

    protected final Log log = LogFactory.getLog(this.getClass());

    private final ItemEventSupport eventSupport = new ItemEventSupport();

    /**
     * Stores the items for this element. Populated when an item is dropped.
     * Reset to null when the last item is picked up. The items are handled as a
     * stack (LIFO data structure). A regular floor tile has 4 sectors where
     * items can be stacked hence the Map<Sector, Stack<Item>>.
     */
    private Map<Sector, Stack<Item>> items;

    public ItemManager() {
    }

    @Override
    public void addItemListener(ItemListener listener) {
        eventSupport.addItemListener(listener);
    }

    @Override
    public void removeItemListener(ItemListener listener) {
        eventSupport.removeItemListener(listener);
    }

    private void fireItemRemovedEvent(Item item, Sector sector) {
        eventSupport.fireItemRemovedEvent(new ItemEvent(this, item, sector));
    }

    private void fireItemAddedEvent(Item item, Sector sector) {
        eventSupport.fireItemAddedEvent(new ItemEvent(this, item, sector));
    }

    @Override
    public synchronized void addItem(Item item, Sector sector) {
        Validate.notNull(item, "The given item is null");
        Validate.notNull(sector, "The given sector is null");

        if (items == null) {
            items = new EnumMap<Sector, Stack<Item>>(Sector.class);
        }

        Stack<Item> stack = items.get(sector);

        if (stack == null) {
            items.put(sector, stack = new Stack<Item>());
        }

        stack.push(item);

        fireItemAddedEvent(item, sector);
    }

    @Override
    public synchronized Sector addItem(Item item) {
        Validate.notNull(item, "The given item is null");

        final Sector sector = Sector.random();
        addItem(item, sector);

        return sector;
    }

    @Override
    public synchronized Item removeItem(Sector sector) {
        Validate.notNull(sector, "The given sector is null");

        if (items != null) {
            final Stack<Item> stack = items.get(sector);

            if (stack != null) {
                // Remove the top item from the stack
                final Item item = stack.pop();

                if (stack.isEmpty()) {
                    items.remove(sector);

                    if (items.isEmpty()) {
                        items = null;
                    }
                }

                fireItemRemovedEvent(item, sector);

                return item;
            }
        }

        return null;
    }

    @Override
    public synchronized Item removeItem() {
        if (items == null) {
            return null;
        }

        final List<Sector> sectors = new ArrayList<Sector>(items.keySet());

        if (sectors.isEmpty()) {
            // Not supposed to happen
            return null;
        }

        Collections.shuffle(sectors);

        return removeItem(sectors.iterator().next());
    }

    @Override
    public final Sector getPlace(Item item) {
        Validate.notNull(item, "The given item is null");

        if (items != null) {
            for (Sector sector : items.keySet()) {
                final Stack<Item> stack = items.get(sector);

                if ((stack != null) && stack.contains(item)) {
                    return sector;
                }
            }
        }

        // Can't find item
        return null;
    }

    @Override
    public final List<Item> getItems() {
        if (items != null) {
            final List<Item> list = new ArrayList<Item>();

            for (Stack<Item> stack : items.values()) {
                list.addAll(stack);
            }

            return list;
        }

        // No item on the floor
        return Collections.emptyList();
    }

    @Override
    public final int getItemCount() {
        int count = 0;

        if (items != null) {
            for (Stack<Item> stack : items.values()) {
                count += stack.size();
            }
        }

        return count;
    }

    @Override
    public final int getItemCount(Sector sector) {
        Validate.notNull(sector, "The given sector is null");

        if (items != null) {
            final Stack<Item> stack = items.get(sector);

            return (stack != null) ? stack.size() : 0;
        }

        // No item on the floor
        return 0;
    }

    @Override
    public List<Item> getItems(Sector sector) {
        Validate.isTrue(sector != null, "The given sector is null");

        if (items != null) {
            final List<Item> list = items.get(sector);

            if (list != null) {
                // Defensive recopy
                return new ArrayList<Item>(list);
            }
        }

        return Collections.emptyList();
    }

    @Override
    public boolean hasItems() {
        if (items != null) {
            for (Stack<Item> stack : items.values()) {
                if (!stack.isEmpty()) {
                    return true;
                }
            }
        }

        return false;
    }

    @Override
    public boolean removeItem(Item item) {
        return removeItem(getPlace(item)) == item;
    }

    @Override
    public Sector getRandomPlace() {
        if (items == null) {
            return null;
        }

        final List<Sector> sectors = new ArrayList<Sector>(items.keySet());

        if (sectors.isEmpty()) {
            // Not supposed to happen
            return null;
        }

        Collections.shuffle(sectors);

        return sectors.iterator().next();
    }
}