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    package org.apache.oozie.workflow.lite;
019    
020    import org.apache.hadoop.io.Writable;
021    import org.apache.oozie.service.LiteWorkflowStoreService;
022    import org.apache.oozie.util.ParamChecker;
023    import org.apache.oozie.workflow.WorkflowException;
024    
025    import java.io.DataInput;
026    import java.io.DataOutput;
027    import java.io.IOException;
028    import java.util.ArrayList;
029    import java.util.Collections;
030    import 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     */
036    public 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    }