001/*
002 * Copyright (c) 2007-2016 Concurrent, Inc. All Rights Reserved.
003 *
004 * Project and contact information: http://www.cascading.org/
005 *
006 * This file is part of the Cascading project.
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *     http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020
021package cascading.flow.planner;
022
023import cascading.flow.FlowElement;
024import cascading.flow.FlowException;
025import cascading.flow.planner.graph.ElementGraph;
026import cascading.flow.planner.iso.finder.GraphFinderException;
027import cascading.flow.planner.rule.PlanPhase;
028import cascading.flow.planner.rule.Rule;
029import cascading.flow.planner.rule.RuleRegistry;
030import cascading.util.TraceUtil;
031
032/**
033 * Class PlannerException is thrown when a job planner fails.
034 * <p/>
035 * For debugging purposes, the PlannerException holds a copy of the internal job representation which can be
036 * written out to disk and visualized with tools that support the
037 * <a href="http://en.wikipedia.org/wiki/DOT_language">DOT file format</a> using the {@link #writeDOT(String)}
038 * method.
039 */
040public class PlannerException extends FlowException
041  {
042  /** Field pipeGraph */
043  ElementGraph elementGraph;
044
045  /** Constructor PlannerException creates a new PlannerException instance. */
046  public PlannerException()
047    {
048    }
049
050  /**
051   * Constructor PlannerException creates a new PlannerException instance.
052   *
053   * @param flowElement of type FlowElement
054   * @param message     of type String
055   */
056  public PlannerException( FlowElement flowElement, String message )
057    {
058    super( TraceUtil.formatTrace( flowElement, message ) );
059    }
060
061  /**
062   * Constructor PlannerException creates a new PlannerException instance.
063   *
064   * @param flowElement of type FlowElement
065   * @param message     of type String
066   * @param throwable   of type Throwable
067   */
068  public PlannerException( FlowElement flowElement, String message, Throwable throwable )
069    {
070    super( TraceUtil.formatTrace( flowElement, message ), throwable );
071    }
072
073  /**
074   * Constructor PlannerException creates a new PlannerException instance.
075   *
076   * @param flowElement  of type FlowElement
077   * @param message      of type String
078   * @param throwable    of type Throwable
079   * @param elementGraph of type ElementGraph
080   */
081  public PlannerException( FlowElement flowElement, String message, Throwable throwable, ElementGraph elementGraph )
082    {
083    super( TraceUtil.formatTrace( flowElement, message ), throwable );
084    this.elementGraph = elementGraph;
085    }
086
087  /**
088   * Constructor PlannerException creates a new PlannerException instance.
089   *
090   * @param string of type String
091   */
092  public PlannerException( String string )
093    {
094    super( string );
095    }
096
097  /**
098   * Constructor PlannerException creates a new PlannerException instance.
099   *
100   * @param string    of type String
101   * @param throwable of type Throwable
102   */
103  public PlannerException( String string, Throwable throwable )
104    {
105    super( string, throwable );
106    }
107
108  /**
109   * Constructor PlannerException creates a new PlannerException instance.
110   *
111   * @param throwable of type Throwable
112   */
113  public PlannerException( Throwable throwable )
114    {
115    super( throwable );
116    }
117
118  /**
119   * Constructor PlannerException creates a new PlannerException instance.
120   *
121   * @param string       of type String
122   * @param elementGraph of type SimpleDirectedGraph<FlowElement, Scope>
123   */
124  public PlannerException( String string, ElementGraph elementGraph )
125    {
126    super( string );
127    this.elementGraph = elementGraph;
128    }
129
130  /**
131   * Constructor PlannerException creates a new PlannerException instance.
132   *
133   * @param string       of type String
134   * @param throwable    of type Throwable
135   * @param elementGraph of type SimpleDirectedGraph<FlowElement, Scope>
136   */
137  public PlannerException( String string, Throwable throwable, ElementGraph elementGraph )
138    {
139    super( string, throwable );
140    this.elementGraph = elementGraph;
141    }
142
143  public PlannerException( Rule rule, Exception exception )
144    {
145    super( "failed on rule: " + rule.getRuleName(), exception );
146    }
147
148  public PlannerException( PlanPhase phase, Rule rule, Throwable throwable )
149    {
150    super( "phase: " + phase + ", failed on rule: " + rule.getRuleName(), throwable );
151    }
152
153  public PlannerException( PlanPhase phase, Rule rule, ElementGraph elementGraph, Throwable throwable )
154    {
155    super( "phase: " + phase + ", failed on rule: " + rule.getRuleName() + ( elementGraph != null ? ", see attached source element-graph" : "" ), throwable );
156    this.elementGraph = elementGraph;
157    }
158
159  public PlannerException( RuleRegistry registry, PlanPhase phase, Rule rule, Throwable throwable )
160    {
161    super( "registry: " + registry.getName() + ", phase: " + phase + ", failed on rule: " + rule.getRuleName(), throwable );
162    }
163
164  public PlannerException( RuleRegistry registry, PlanPhase phase, Rule rule, ElementGraph elementGraph, Throwable throwable )
165    {
166    super( "registry: " + registry.getName() + ", phase: " + phase + ", failed on rule: " + rule.getRuleName() + ( elementGraph != null ? ", see attached source element-graph" : "" ), throwable );
167    this.elementGraph = elementGraph;
168    }
169
170  /**
171   * Method getElementGraph returns the elementGraph of this PlannerException object.
172   *
173   * @return the pipeGraph (ElementGraph) of this PlannerException object.
174   */
175  public ElementGraph getElementGraph()
176    {
177    return elementGraph;
178    }
179
180  /**
181   * Method writeDOT writes the failed Flow instance to the given filename as a DOT file for import into a graphics package.
182   *
183   * @param filename of type String
184   */
185  public void writeDOT( String filename )
186    {
187    if( elementGraph == null )
188      return;
189
190    elementGraph.writeDOT( filename );
191    }
192
193  /**
194   * Method writeCauseDOT writes the underlying {@link cascading.flow.planner.iso.finder.GraphFinderException}
195   * intermediate graph as a DOT file.
196   * <p/>
197   * If the cause is not a GraphFinderException, and the underlying graph doesn't provide a 'writeDOT' method,
198   * the method does nothing.
199   *
200   * @param filename of type String
201   */
202  public void writeCauseDOT( String filename )
203    {
204    if( getCause() instanceof GraphFinderException )
205      ( (GraphFinderException) getCause() ).writeDOT( filename );
206    }
207  }