View Javadoc

1   /*
2    * Copyright (C) 2006  Tom Gibara
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 2.1 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not, write to the Free Software
16   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17   */
18  package com.tomgibara.pronto.config.source;
19  
20  import java.util.HashMap;
21  import java.util.Map;
22  
23  import com.tomgibara.pronto.util.Arguments;
24  
25  /**
26   * Instances of this class can compute accurate values for lastModified from
27   * property maps alone.
28   * 
29   * The property maps supplied to these objects are not modified and are copied
30   * if their values need to be recorded by this object. The copies made in this
31   * way are available via the getProperties() method.
32   * 
33   * @author Tom Gibara
34   * 
35   */
36  
37  // relies on testing via MapConfigSource
38  public final class LastModifiedCalculator {
39  
40      /** The properties as they were when last changed. */
41      private Map<String, String> properties;
42  
43      /** The time at which the properties were last changed. */
44      private long lastModified;
45  
46      /**
47       * Initializes the object without a known last modified date or known
48       * properties. The update method must be called before these fields are
49       * accessed.
50       */
51  
52      public LastModifiedCalculator() {
53          properties = null;
54          lastModified = 0L;
55      }
56  
57      /**
58       * After calling this constructor, the lastModified field will equal the
59       * supplied lastModified date and the properties field will contain a copy
60       * of the supplied properties.
61       * 
62       * @param properties
63       *            the initial properties for this object, not null
64       * @param lastModified
65       *            the known last modification date for the supplied properties,
66       *            not negative
67       */
68  
69      public LastModifiedCalculator(final Map<String, String> properties, final long lastModified) {
70          Arguments.notNull(properties, "properties");
71          Arguments.notNegative(lastModified, "lastModified");
72          this.properties = new HashMap<String, String>(properties);
73          this.lastModified = lastModified;
74      }
75  
76      /**
77       * Computes the lastModified field of this object based on the supplied map.
78       * 
79       * This method will persist a copy of the supplied properties if the
80       * properties differ from the last call to this method (or if this is the
81       * first call to the method).
82       * 
83       * @param properties a new collection of properties
84       */
85  
86      public void update(final Map<String, String> properties) {
87          Arguments.notNull(properties, "properties");
88          if (this.properties == null) { // case: first supplied map
89              doUpdate(properties);
90          } else if (properties == this.properties) { // case: same map
91              // this is possible if the client code passes properties back in
92              /* nothing to do */
93          } else if (properties.equals(this.properties)) { // case: equal map
94              /* nothing to do */
95          } else { // case: map has changed
96              doUpdate(properties);
97          }
98      }
99  
100     /**
101      * Returns a copy of the last supplied properties which had changed.
102      * 
103      * @return the properties recorded by this object, never null
104      * @throws IllegalStateException
105      *             if the update method has not yet been called
106      */
107 
108     public Map<String, String> getProperties() throws IllegalStateException {
109         if (properties == null) throw new IllegalStateException("Last modified time requested before update.");
110         return properties;
111     }
112 
113     /**
114      * Returns the lastModified date maintained by this object.
115      * 
116      * @return the time at which the properties stored by this object were last
117      *         modified
118      * @throws IllegalStateException
119      *             if the update method has not yet been called
120      */
121 
122     public long getLastModified() throws IllegalStateException {
123         if (properties == null) throw new IllegalStateException("Properties requested before update.");
124         return lastModified;
125     }
126 
127     // private utility methods
128 
129     /**
130      * Update the fields of this object based on the supplied map.
131      * 
132      * @param properties
133      *            the properties to record
134      */
135 
136     private void doUpdate(final Map<String, String> properties) {
137         this.properties = new HashMap<String, String>(properties);
138         long lastModified = System.currentTimeMillis();
139         // we need to watch out for future last modified times being supplied to
140         // constructor
141         if (this.lastModified < lastModified) this.lastModified = lastModified;
142     }
143 
144 }