/******************************************************************************* * Copyright (c) 2007 - 2007 IT Solutions, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Robert Munteanu *******************************************************************************/ package com.itsolut.mantis.core; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.*; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.itsolut.mantis.core.model.*; /** * @author Robert Munteanu * */ public class MantisCacheData implements Serializable { // increment when structure changes private static final long serialVersionUID = 9L; private long lastUpdate = 0; private List<MantisProject> projects = new ArrayList<MantisProject>(); private ArrayListMultimapHolder<Integer, MantisProjectFilter> projectFiltersById = ArrayListMultimapHolder.create(); private ArrayListMultimapHolder<Integer,MantisCustomField> customFieldsByProjectId = ArrayListMultimapHolder.create(); RepositoryVersion repositoryVersion; int resolvedStatus; List<MantisPriority> priorities; List<MantisTicketStatus> statuses; List<MantisSeverity> severities; List<MantisResolution> resolutions; List<MantisReproducibility> reproducibilities; List<MantisProjection> projections; List<MantisETA> etas; List<MantisViewState> viewStates; Map<Integer, List<MantisProjectCategory>> categoriesByProjectId = new HashMap<Integer, List<MantisProjectCategory>>(); private ArrayListMultimapHolder<Integer, MantisVersion> versionsByProjectId = ArrayListMultimapHolder.create(); private ArrayListMultimapHolder<Integer, MantisUser> reportersByProjectId = ArrayListMultimapHolder.create(); private ArrayListMultimapHolder<Integer, MantisUser> developersByProjectId = ArrayListMultimapHolder.create(); private int reporterThreshold; private int developerThreshold; int dueDateUpdateThreshold; int dueDateViewThreshold; public boolean timeTrackingEnabled; int bugSubmitStatus; int bugAssignedStatus; private Map<MantisTicket.Key, Integer> defaultValuesForAttributes = new EnumMap<MantisTicket.Key, Integer>(MantisTicket.Key.class); private Map<MantisTicket.Key, String> defaultStringValuesForAttributes = new EnumMap<MantisTicket.Key, String>(MantisTicket.Key.class); private Map<Integer, MantisTag> tagsById; private int bugResolutionFixedThreshold; private boolean etaEnabled; private boolean projectionEnabled; Map<String, MantisUser> allUsers = new HashMap<String, MantisUser>(); private boolean enableProfiles; public boolean hasBeenRefreshed() { return lastUpdate != 0; } public void setLastUpdate(long lastUpdate) { this.lastUpdate = lastUpdate; } public List<MantisProject> getProjects() { return projects; } public void setProjects(List<MantisProject> projects) { this.projects = projects; } public int getDeveloperThreshold() { return developerThreshold; } public void setDeveloperThreshold(int developerThreshold) { this.developerThreshold = developerThreshold; } public int getReporterThreshold() { return reporterThreshold; } public void setReporterThreshold(int reporterThreshold) { this.reporterThreshold = reporterThreshold; } public ListMultimap<Integer, MantisUser> getReportersByProjectId() { if ( reportersByProjectId == null ) reportersByProjectId = ArrayListMultimapHolder.create(); return reportersByProjectId.get(); } public ListMultimap<Integer, MantisUser> getDevelopersByProjectId() { if ( developersByProjectId == null ) developersByProjectId = ArrayListMultimapHolder.create(); return developersByProjectId.get(); } public void putDefaultValueForAttribute(MantisTicket.Key key, Integer value) { defaultValuesForAttributes.put(key, value); } public Integer getDefaultValueForAttribute(MantisTicket.Key key ) { return defaultValuesForAttributes.get(key); } public void putDefaultValueForStringAttribute(MantisTicket.Key key, String value) { defaultStringValuesForAttributes.put(key, value); } public String getDefaultValueForStringAttribute(MantisTicket.Key key ) { return defaultStringValuesForAttributes.get(key); } public int getBugResolutionFixedThreshold() { return bugResolutionFixedThreshold; } public void setBugResolutionFixedThreshold(int bugResolutionFixedThreshold) { this.bugResolutionFixedThreshold = bugResolutionFixedThreshold; } public boolean isEtaEnabled() { return etaEnabled; } public void setEtaEnabled(boolean etaEnabled) { this.etaEnabled = etaEnabled; } public boolean isProjectionEnabled() { return projectionEnabled; } public void setProjectionEnabled(boolean projectionEnabled) { this.projectionEnabled = projectionEnabled; } public ListMultimap<Integer, MantisVersion> getVersionsByProjectId() { if ( versionsByProjectId == null ) versionsByProjectId = ArrayListMultimapHolder.create(); return versionsByProjectId.get(); } public ListMultimap<Integer, MantisProjectFilter> getProjectFiltersById() { if ( projectFiltersById == null ) projectFiltersById = ArrayListMultimapHolder.create(); return projectFiltersById.get(); } public ListMultimap<Integer, MantisCustomField> getCustomFieldsByProjectId() { if ( customFieldsByProjectId == null ) customFieldsByProjectId = ArrayListMultimapHolder.create(); return customFieldsByProjectId.get(); } public Map<Integer, MantisTag> getTagsById() { return Collections.unmodifiableMap(tagsById); } public void setTagsById(Map<Integer, MantisTag> tagsById ) { if ( this.tagsById == null ) this.tagsById = Maps.newHashMapWithExpectedSize(tagsById.size()); this.tagsById.clear(); this.tagsById.putAll(tagsById); } /** * This class allows safe serialisation of a {@link ArrayListMultimap} in an OSGI environment * * <p>When reading a serialized version of a multimap, the classloaded does not have access to * the classes from the <tt>com.itsolut.mantis.core</tt> bundle, and it does not have have a * <tt>Eclipse-BuddyPolicy:Registered</tt> header , which means we can not use * <tt>RegisterBuddy</tt> to allow it to access our classes.</p> * * <p>This class simply wraps a multimap instance and serializes it as a map of * {@literal K -> Collection<V> }</p< * */ private static class ArrayListMultimapHolder<K, V> implements Serializable { // copied from ArrayListMultimap.DEFAULT_VALUES_PER_KEY private static final int DEFAULT_VALUES_PER_KEY = 10; public static <K,V> ArrayListMultimapHolder<K, V> create() { return new ArrayListMultimapHolder<K, V>(); } private ArrayListMultimap<K, V> wrapped = ArrayListMultimap.create(); public ArrayListMultimapHolder() { } public ArrayListMultimap<K, V> get() { return wrapped; } private void writeObject(ObjectOutputStream out) throws IOException { Map<K, Collection<V>> wrappedMap = wrapped.asMap(); Map<K, Collection<V>> outMap = Maps.newHashMapWithExpectedSize(wrappedMap.size()); for ( Map.Entry<K, Collection<V>> entry : wrappedMap.entrySet() ) outMap.put(entry.getKey(), Lists.newArrayList(entry.getValue())); out.writeObject(outMap); } private void readObject(ObjectInputStream in) throws IOException { try { @SuppressWarnings("unchecked") Map<K, Collection<V>> map = (Map<K, Collection<V>>) in.readObject(); wrapped = ArrayListMultimap.create(map.size(), DEFAULT_VALUES_PER_KEY); for ( Map.Entry<K, Collection<V>> entry : map.entrySet() ) wrapped.putAll(entry.getKey(), entry.getValue()); } catch (ClassNotFoundException e) { IOException e2 = new IOException(); e2.initCause(e); throw e2; } } } public void setEnableProfiles(boolean enableProfiles) { this.enableProfiles = enableProfiles; } public boolean isEnableProfiles() { return enableProfiles; } }