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