001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *      http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.oozie.workflow.lite;
020
021import org.apache.hadoop.io.Writable;
022import org.apache.oozie.service.LiteWorkflowStoreService;
023import org.apache.oozie.util.ParamChecker;
024import org.apache.oozie.workflow.WorkflowException;
025
026import java.io.DataInput;
027import java.io.DataOutput;
028import java.io.IOException;
029import java.util.ArrayList;
030import java.util.Collections;
031import java.util.List;
032
033/**
034 * This node definition is serialized object and should provide readFields() and write() for read and write of fields in
035 * this class.
036 */
037public class NodeDef implements Writable {
038    private String nodeDefVersion = null;
039    private String name = null;
040    private Class<? extends NodeHandler> handlerClass;
041    private String conf = null;
042    private List<String> transitions = new ArrayList<String>();
043    private String cred = null;
044    private String userRetryMax = "null";
045    private String userRetryInterval = "null";
046
047    NodeDef() {
048    }
049
050    NodeDef(String name, String conf, Class<? extends NodeHandler> handlerClass, List<String> transitions) {
051        this.name = ParamChecker.notEmpty(name, "name");
052        this.conf = conf;
053        this.handlerClass = ParamChecker.notNull(handlerClass, "handlerClass");
054        this.transitions = Collections.unmodifiableList(ParamChecker.notEmptyElements(transitions, "transitions"));
055    }
056
057    NodeDef(String name, String conf, Class<? extends NodeHandler> handlerClass, List<String> transitions, String cred) {
058        this(name, conf, handlerClass, transitions);
059        if (cred != null) {
060            this.cred = cred;
061        }
062    }
063
064    NodeDef(String name, String conf, Class<? extends NodeHandler> handlerClass, List<String> transitions, String cred,
065            String userRetryMax, String userRetryInterval) {
066        this(name, conf, handlerClass, transitions, cred);
067        if (userRetryMax != null) {
068            this.userRetryMax = userRetryMax;
069        }
070        if (userRetryInterval != null) {
071            this.userRetryInterval = userRetryInterval;
072        }
073    }
074
075    public boolean equals(NodeDef other) {
076        return !(other == null || getClass() != other.getClass() || !getName().equals(other.getName()));
077    }
078
079    @Override
080    public int hashCode() {
081        return name.hashCode();
082    }
083
084    public String getName() {
085        return name;
086    }
087
088    public String getCred() {
089        return cred;
090    }
091
092    public Class<? extends NodeHandler> getHandlerClass() {
093        return handlerClass;
094    }
095
096    public List<String> getTransitions() {
097        return transitions;
098    }
099
100    public String getConf() {
101        return conf;
102    }
103
104    public String getUserRetryMax() {
105        return userRetryMax;
106    }
107
108    public String getUserRetryInterval() {
109        return userRetryInterval;
110    }
111
112    public String getNodeDefVersion() {
113        if (nodeDefVersion == null) {
114            try {
115                nodeDefVersion = LiteWorkflowStoreService.getNodeDefDefaultVersion();
116            }
117            catch (WorkflowException e) {
118                nodeDefVersion = LiteWorkflowStoreService.NODE_DEF_VERSION_1;
119            }
120        }
121        return nodeDefVersion;
122    }
123
124    @SuppressWarnings("unchecked")
125    private void readVersionZero(DataInput dataInput, String firstField) throws IOException {
126        if (firstField.equals(LiteWorkflowStoreService.NODE_DEF_VERSION_0)) {
127            name = dataInput.readUTF();
128        } else {
129            name = firstField;
130        }
131        nodeDefVersion = LiteWorkflowStoreService.NODE_DEF_VERSION_0;
132        cred = dataInput.readUTF();
133        String handlerClassName = dataInput.readUTF();
134        if ((handlerClassName != null) && (handlerClassName.length() > 0)) {
135            try {
136                handlerClass = (Class<? extends NodeHandler>) Class.forName(handlerClassName);
137            }
138            catch (ClassNotFoundException ex) {
139                throw new IOException(ex);
140            }
141        }
142        conf = dataInput.readUTF();
143        if (conf.equals("null")) {
144            conf = null;
145        }
146        int numTrans = dataInput.readInt();
147        transitions = new ArrayList<String>(numTrans);
148        for (int i = 0; i < numTrans; i++) {
149            transitions.add(dataInput.readUTF());
150        }
151    }
152    @SuppressWarnings("unchecked")
153    private void readVersionOne(DataInput dataInput, String firstField) throws IOException {
154        nodeDefVersion = LiteWorkflowStoreService.NODE_DEF_VERSION_1;
155        name = dataInput.readUTF();
156        cred = dataInput.readUTF();
157        if (cred.equals("null")) {
158            cred = null;
159        }
160        String handlerClassName = dataInput.readUTF();
161        if ((handlerClassName != null) && (handlerClassName.length() > 0)) {
162            try {
163                handlerClass = (Class<? extends NodeHandler>) Class.forName(handlerClassName);
164            }
165            catch (ClassNotFoundException ex) {
166                throw new IOException(ex);
167            }
168        }
169        conf = dataInput.readUTF();
170        if (conf.equals("null")) {
171            conf = null;
172        }
173        int numTrans = dataInput.readInt();
174        transitions = new ArrayList<String>(numTrans);
175        for (int i = 0; i < numTrans; i++) {
176            transitions.add(dataInput.readUTF());
177        }
178        userRetryMax = dataInput.readUTF();
179        userRetryInterval = dataInput.readUTF();
180    }
181
182    /* (non-Javadoc)
183     * @see org.apache.hadoop.io.Writable#readFields(java.io.DataInput)
184     */
185    @Override
186    public void readFields(DataInput dataInput) throws IOException {
187        String firstField = dataInput.readUTF();
188        if (!firstField.equals(LiteWorkflowStoreService.NODE_DEF_VERSION_1)) {
189            readVersionZero(dataInput, firstField);
190        } else {
191            //since oozie version 3.1
192            readVersionOne(dataInput, firstField);
193        }
194    }
195
196    private void writeVersionZero(DataOutput dataOutput) throws IOException {
197        dataOutput.writeUTF(nodeDefVersion);
198        dataOutput.writeUTF(name);
199        if (cred != null) {
200            dataOutput.writeUTF(cred);
201        }
202        else {
203            dataOutput.writeUTF("null");
204        }
205        dataOutput.writeUTF(handlerClass.getName());
206        if (conf != null) {
207            dataOutput.writeUTF(conf);
208        }
209        else {
210            dataOutput.writeUTF("null");
211        }
212        dataOutput.writeInt(transitions.size());
213        for (String transition : transitions) {
214            dataOutput.writeUTF(transition);
215        }
216    }
217
218    /**
219     * Write as version one format, this version was since 3.1.
220     *
221     * @param dataOutput data output to serialize node def
222     * @throws IOException thrown if fail to write
223     */
224    private void writeVersionOne(DataOutput dataOutput) throws IOException {
225        dataOutput.writeUTF(nodeDefVersion);
226        dataOutput.writeUTF(name);
227        if (cred != null) {
228            dataOutput.writeUTF(cred);
229        }
230        else {
231            dataOutput.writeUTF("null");
232        }
233        dataOutput.writeUTF(handlerClass.getName());
234        if (conf != null) {
235            dataOutput.writeUTF(conf);
236        }
237        else {
238            dataOutput.writeUTF("null");
239        }
240        dataOutput.writeInt(transitions.size());
241        for (String transition : transitions) {
242            dataOutput.writeUTF(transition);
243        }
244        if (userRetryMax != null) {
245            dataOutput.writeUTF(userRetryMax);
246        }
247        else {
248            dataOutput.writeUTF("null");
249        }
250        if (userRetryInterval != null) {
251            dataOutput.writeUTF(userRetryInterval);
252        }
253        else {
254            dataOutput.writeUTF("null");
255        }
256    }
257
258    /* (non-Javadoc)
259     * @see org.apache.hadoop.io.Writable#write(java.io.DataOutput)
260     */
261    @Override
262    public void write(DataOutput dataOutput) throws IOException {
263        if (!getNodeDefVersion().equals(LiteWorkflowStoreService.NODE_DEF_VERSION_1)) {
264            writeVersionZero(dataOutput);
265        } else {
266            //since oozie version 3.1
267            writeVersionOne(dataOutput);
268        }
269    }
270
271}