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