001/* A base class for analyses on graphs.
002
003 Copyright (c) 2002-2014 The University of Maryland. All rights reserved.
004 Permission is hereby granted, without written agreement and without
005 license or royalty fees, to use, copy, modify, and distribute this
006 software and its documentation for any purpose, provided that the above
007 copyright notice and the following two paragraphs appear in all copies
008 of this software.
009
010 IN NO EVENT SHALL THE UNIVERSITY OF MARYLAND BE LIABLE TO ANY PARTY
011 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
012 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
013 THE UNIVERSITY OF MARYLAND HAS BEEN ADVISED OF THE POSSIBILITY OF
014 SUCH DAMAGE.
015
016 THE UNIVERSITY OF MARYLAND SPECIFICALLY DISCLAIMS ANY WARRANTIES,
017 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
018 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
019 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
020 MARYLAND HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
021 ENHANCEMENTS, OR MODIFICATIONS.
022
023
024 */
025package ptolemy.graph.analysis;
026
027import ptolemy.graph.Graph;
028import ptolemy.graph.analysis.analyzer.Analyzer;
029import ptolemy.graph.analysis.analyzer.GraphAnalyzer;
030import ptolemy.graph.analysis.strategy.CachedStrategy;
031
032///////////////////////////////////////////////////////////////////
033//// Analysis
034
035/**
036 A base class for analyses on graphs.
037 <p>
038 The organization of the package follows:
039 <p>
040 Classes in ptolemy.graph.analysis consists of different wrappers in
041 which a client can plug a requested strategy/algorithm for an analysis.
042 Strategies for a given analysis implement the same interface defined
043 in ptolemy.graph.analysis.analyzer.
044 Therefore from now on we will use the name analyzer for all the strategies
045 that implement the same interface and therefore  solve the same problem.
046 Analysis classes access the plugged-in strategy class through these interfaces.
047 <p>
048 In the base class methods are provided in order to dynamically change the
049 analyzer of the current analysis and also to check if a given analyzer is
050 applicable to the given analysis.
051 <p>
052 Analyzers that can be used in these analyses are a specialized version of
053 analyzers called {@link ptolemy.graph.analysis.analyzer.GraphAnalyzer}.
054 <p>
055 Classes in ptolemy.graph.analysis.analyzer are the interfaces for
056 different strategies(algorithms) used for the analysis. The strategies classes
057 are defined in ptolemy.graph.analysis.strategy
058 <p>
059 In addition, the analysis classes provide default constructors which use
060 predefined strategies for those clients who do not want to deal with different
061 strategies.
062 Although this introduces some limitations imposed by the used strategy. The
063 documentation of such constructor will reflect the limitations, if any.
064 <p>
065 Finally, strategies can be instantiated and used independently. In this case
066 the client will lose the possibility of dynamically changing the analyzer for
067 the associated analysis, which would not exist at all, and there will be no
068 default constructor therefore the client need to be familiar with the strategy
069 that she/he is using.
070
071 @since Ptolemy II 2.0
072 @Pt.ProposedRating Red (shahrooz)
073 @Pt.AcceptedRating Red (ssb)
074 @author Shahrooz Shahparnia, Shuvra S. Bhattacharyya
075 @version $Id$
076 */
077public class Analysis {
078    /** Construct an analysis using a given analyzer.
079     *
080     *  @param analyzer The given analyzer.
081     */
082    public Analysis(GraphAnalyzer analyzer) {
083        _analyzer = analyzer;
084
085        // Maybe we may want to implement the Observer pattern instead of this.
086        graph().addAnalysis(this);
087    }
088
089    ///////////////////////////////////////////////////////////////////
090    ////                         public methods                    ////
091
092    /** Return the analyzer associated with this analysis class.
093     *
094     *  @return Return the analyzer associated with this analysis class.
095     */
096    public GraphAnalyzer analyzer() {
097        return _analyzer;
098    }
099
100    /** Change the analyzer associated with this analysis class to the given
101     *  analyzer.
102     *
103     *  @param analyzer The given analyzer.
104     *  @exception InvalidAnalyzerException If the analyzer is not a valid
105     *  analyzer for this analysis.
106     */
107    public void changeAnalyzer(GraphAnalyzer analyzer) {
108        if (validAnalyzerInterface(analyzer)) {
109            if (analyzer instanceof CachedStrategy) {
110                if (graph() == analyzer().graph()) {
111                    ((CachedStrategy) analyzer)
112                            .setCachedResult((CachedStrategy) _analyzer);
113                }
114            }
115
116            _analyzer = analyzer;
117        } else {
118            throw new InvalidAnalyzerException(
119                    "Invalid analyzer for the analysis:\n" + toString());
120        }
121    }
122
123    /** The graph associated with the analysis. This association is made
124     *  through the associated analyzer interface.
125     *
126     *  @return Return the graph under analysis.
127     */
128    public Graph graph() {
129        return _analyzer.graph();
130    }
131
132    /** Return a description of the analysis and the associated analyzer.
133     *  It should be overridden in derived classes to
134     *  include details associated with the associated analysis/analyzer.
135     *
136     *  @return A description of the analysis and the associated analyzer.
137     */
138    @Override
139    public String toString() {
140        return "Analysis using the following analyzer:\n"
141                + _analyzer.toString();
142    }
143
144    /** Return the validity of the associated analyzer. An analyzer is valid
145     *  if the graph and the associated data is in a format suitable for the
146     *  analyzer.
147     *
148     *  @return Return the validity of the associated analyzer.
149     */
150    public boolean valid() {
151        return _analyzer.valid();
152    }
153
154    /** Check if a given analyzer is compatible with this analysis.
155     *  In other words if it is possible to use it to compute the computation
156     *  associated with this analysis.
157     *  Derived classes should override this method to provide the valid type
158     *  of analyzer that they need.
159     *
160     *  @param analyzer The given analyzer.
161     *  @return True if the given analyzer is valid for this analysis.
162     */
163    public boolean validAnalyzerInterface(Analyzer analyzer) {
164        return analyzer instanceof GraphAnalyzer;
165    }
166
167    ///////////////////////////////////////////////////////////////////
168    ////                         private variables                 ////
169    // The analyzer that is used in the computation of this analysis.
170    private GraphAnalyzer _analyzer;
171}