You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@oozie.apache.org by an...@apache.org on 2018/06/19 09:47:04 UTC
[14/16] oozie git commit: OOZIE-2339 [fluent-job] Minimum Viable
Fluent Job API (daniel.becker, andras.piros via rkanter, gezapeti, pbacsko)
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ActionAttributesBuilder.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ActionAttributesBuilder.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ActionAttributesBuilder.java
new file mode 100644
index 0000000..d52b9c9
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ActionAttributesBuilder.java
@@ -0,0 +1,567 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.oozie.fluentjob.api.ModifyOnce;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A builder class for {@link ActionAttributes}.
+ *
+ * The properties of the builder can only be set once, an attempt to set them a second time will trigger
+ * an {@link IllegalStateException}. The properties that are lists are an exception to this rule, of course multiple
+ * elements can be added / removed.
+ *
+ * Builder instances can be used to build several elements, although properties already set cannot be changed after
+ * a call to {@link ActionAttributesBuilder#build} either.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class ActionAttributesBuilder implements Builder<ActionAttributes> {
+ private final ModifyOnce<String> resourceManager;
+ private final ModifyOnce<String> nameNode;
+ private final ModifyOnce<Prepare> prepare;
+ private final ModifyOnce<Streaming> streaming;
+ private final ModifyOnce<Pipes> pipes;
+ private final List<String> jobXmls;
+ private final Map<String, ModifyOnce<String>> configuration;
+ private final ModifyOnce<String> configClass;
+ private final List<String> files;
+ private final List<String> archives;
+ private final List<Delete> deletes;
+ private final List<Mkdir> mkdirs;
+ private final List<Move> moves;
+ private final List<Chmod> chmods;
+ private final List<Touchz> touchzs;
+ private final List<Chgrp> chgrps;
+ private final ModifyOnce<String> javaOpts;
+ private final List<String> args;
+ private final ModifyOnce<Launcher> launcher;
+ private final ModifyOnce<Boolean> captureOutput;
+
+ /**
+ * Creates and returns an empty builder.
+ * @return An empty builder.
+ */
+ public static ActionAttributesBuilder create() {
+ final ModifyOnce<String> resourceManager = new ModifyOnce<>();
+ final ModifyOnce<String> nameNode = new ModifyOnce<>();
+ final ModifyOnce<Prepare> prepare = new ModifyOnce<>();
+ final ModifyOnce<Streaming> streaming = new ModifyOnce<>();
+ final ModifyOnce<Pipes> pipes = new ModifyOnce<>();
+ final List<String> jobXmls = new ArrayList<>();
+ final Map<String, ModifyOnce<String>> configuration = new LinkedHashMap<>();
+ final ModifyOnce<String> configClass = new ModifyOnce<>();
+ final List<String> files = new ArrayList<>();
+ final List<String> archives = new ArrayList<>();
+ final List<Delete> deletes = new ArrayList<>();
+ final List<Mkdir> mkdirs = new ArrayList<>();
+ final List<Move> moves = new ArrayList<>();
+ final List<Chmod> chmods = new ArrayList<>();
+ final List<Touchz> touchzs = new ArrayList<>();
+ final List<Chgrp> chgrps = new ArrayList<>();
+ final ModifyOnce<String> javaOpts = new ModifyOnce<>();
+ final List<String> args = new ArrayList<>();
+ final ModifyOnce<Launcher> launcher = new ModifyOnce<>();
+ final ModifyOnce<Boolean> captureOutput = new ModifyOnce<>();
+
+ return new ActionAttributesBuilder(
+ resourceManager,
+ prepare,
+ streaming,
+ pipes,
+ jobXmls,
+ configuration,
+ configClass,
+ files,
+ archives,
+ deletes,
+ mkdirs,
+ moves,
+ chmods,
+ touchzs,
+ chgrps,
+ javaOpts,
+ args,
+ nameNode,
+ launcher,
+ captureOutput);
+ }
+
+ /**
+ * Create and return a new {@link ActionAttributesBuilder} that is based on an already built
+ * {@link ActionAttributes} object. The properties of the builder will initially be the same as those of the
+ * provided {@link ActionAttributes} object, but it is possible to modify them once.
+ * @param attributes The {@link ActionAttributes} object on which this {@link ActionAttributesBuilder} will be based.
+ * @return A new {@link ActionAttributesBuilder} that is based on a previously built
+ * {@link ActionAttributes} object.
+ */
+ public static ActionAttributesBuilder createFromExisting(final ActionAttributes attributes) {
+ final ModifyOnce<String> resourceManager = new ModifyOnce<>(attributes.getResourceManager());
+ final ModifyOnce<String> nameNode = new ModifyOnce<>(attributes.getNameNode());
+ final ModifyOnce<Prepare> prepare = new ModifyOnce<>(attributes.getPrepare());
+ final ModifyOnce<Streaming> streaming = new ModifyOnce<>(attributes.getStreaming());
+ final ModifyOnce<Pipes> pipes = new ModifyOnce<>(attributes.getPipes());
+ final List<String> jobXmls = new ArrayList<>(attributes.getJobXmls());
+ final Map<String, ModifyOnce<String>> configuration = convertToModifyOnceMap(attributes.getConfiguration());
+ final ModifyOnce<String> configClass = new ModifyOnce<>(attributes.getConfigClass());
+ final List<String> files = new ArrayList<>(attributes.getFiles());
+ final List<String> archives = new ArrayList<>(attributes.getArchives());
+ final List<Delete> deletes = new ArrayList<>(attributes.getDeletes());
+ final List<Mkdir> mkdirs = new ArrayList<>(attributes.getMkdirs());
+ final List<Move> moves = new ArrayList<>(attributes.getMoves());
+ final List<Chmod> chmods = new ArrayList<>(attributes.getChmods());
+ final List<Touchz> touchzs = new ArrayList<>(attributes.getTouchzs());
+ final List<Chgrp> chgrps = new ArrayList<>(attributes.getChgrps());
+ final ModifyOnce<String> javaOpts = new ModifyOnce<>(attributes.getJavaOpts());
+ final List<String> args = new ArrayList<>(attributes.getArgs());
+ final ModifyOnce<Launcher> launcher = new ModifyOnce<>(attributes.getLauncher());
+ final ModifyOnce<Boolean> captureOutput = new ModifyOnce<>(attributes.isCaptureOutput());
+
+ return new ActionAttributesBuilder(
+ resourceManager,
+ prepare,
+ streaming,
+ pipes,
+ jobXmls,
+ configuration,
+ configClass,
+ files,
+ archives,
+ deletes,
+ mkdirs,
+ moves,
+ chmods,
+ touchzs,
+ chgrps,
+ javaOpts,
+ args,
+ nameNode,
+ launcher,
+ captureOutput);
+ }
+
+ public static ActionAttributesBuilder createFromAction(final Node action) {
+ if (HasAttributes.class.isAssignableFrom(action.getClass()) && action instanceof HasAttributes) {
+ return ActionAttributesBuilder.createFromExisting(((HasAttributes) action).getAttributes());
+ }
+
+ return ActionAttributesBuilder.create();
+ }
+
+ private ActionAttributesBuilder(final ModifyOnce<String> resourceManager,
+ final ModifyOnce<Prepare> prepare,
+ final ModifyOnce<Streaming> streaming,
+ final ModifyOnce<Pipes> pipes,
+ final List<String> jobXmls,
+ final Map<String, ModifyOnce<String>> configuration,
+ final ModifyOnce<String> configClass,
+ final List<String> files,
+ final List<String> archives,
+ final List<Delete> deletes,
+ final List<Mkdir> mkdirs,
+ final List<Move> moves,
+ final List<Chmod> chmods,
+ final List<Touchz> touchzs,
+ final List<Chgrp> chgrps,
+ final ModifyOnce<String> javaOpts,
+ final List<String> args,
+ final ModifyOnce<String> nameNode,
+ final ModifyOnce<Launcher> launcher,
+ final ModifyOnce<Boolean> captureOutput) {
+ this.nameNode = nameNode;
+ this.prepare = prepare;
+ this.streaming = streaming;
+ this.pipes = pipes;
+ this.jobXmls = jobXmls;
+ this.configuration = configuration;
+ this.configClass = configClass;
+ this.files = files;
+ this.archives = archives;
+ this.deletes = deletes;
+ this.mkdirs = mkdirs;
+ this.moves = moves;
+ this.chmods = chmods;
+ this.touchzs = touchzs;
+ this.chgrps = chgrps;
+ this.javaOpts = javaOpts;
+ this.args = args;
+ this.resourceManager = resourceManager;
+ this.launcher = launcher;
+ this.captureOutput = captureOutput;
+ }
+
+ public void withResourceManager(final String resourceManager) {
+ this.resourceManager.set(resourceManager);
+ }
+
+ /**
+ * Registers a name node.
+ * @param nameNode The string representing the name node.
+ * @throws IllegalStateException if a name node has already been set on this builder.
+ */
+ public void withNameNode(final String nameNode) {
+ this.nameNode.set(nameNode);
+ }
+
+ /**
+ * Registers a {@link Prepare} object.
+ * @param prepare The {@link Prepare} object to register.
+ * @throws IllegalStateException if a {@link Prepare} object has already been set on this builder.
+ */
+ void withPrepare(final Prepare prepare) {
+ this.prepare.set(prepare);
+ }
+
+ /**
+ * Registers a {@link Streaming} object.
+ * @param streaming The {@link Streaming} object to register.
+ * @throws IllegalStateException if a {@link Streaming} object has already been set on this builder.
+ */
+ void withStreaming(final Streaming streaming) {
+ this.streaming.set(streaming);
+ }
+
+ /**
+ * Registers a {@link Pipes} object.
+ * @param pipes The {@link Pipes} object to register.
+ * @throws IllegalStateException if a {@link Pipes} object has already been set on this builder.
+ */
+ void withPipes(final Pipes pipes) {
+ this.pipes.set(pipes);
+ }
+
+ /**
+ * Registers a job XML with this builder.
+ * @param jobXml The job XML to register.
+ */
+ public void withJobXml(final String jobXml) {
+ this.jobXmls.add(jobXml);
+ }
+
+ /**
+ * Removes a job XML if it is registered with this builder, otherwise does nothing.
+ * @param jobXml The job XML to remove.
+ */
+ public void withoutJobXml(final String jobXml) {
+ jobXmls.remove(jobXml);
+ }
+
+ /**
+ * Removes all job XMLs that are registered with this builder.
+ */
+ public void clearJobXmls() {
+ jobXmls.clear();
+ }
+
+ /**
+ * Registers a configuration property (a key-value pair) with this builder. If the provided key has already been
+ * set on this builder, an exception is thrown. Setting a key to null means deleting it.
+ * @param key The name of the property to set.
+ * @param value The value of the property to set.
+ * @throws IllegalStateException if the provided key has already been set on this builder.
+ */
+ public void withConfigProperty(final String key, final String value) {
+ ModifyOnce<String> mappedValue = this.configuration.get(key);
+
+ if (mappedValue == null) {
+ mappedValue = new ModifyOnce<>(value);
+ this.configuration.put(key, mappedValue);
+ }
+
+ mappedValue.set(value);
+ }
+
+ /**
+ * Registers a configuration class with this builder.
+ * @param configClass The string representing the configuration class.
+ * @throws IllegalStateException if a configuration class has already been set on this builder.
+ */
+ void withConfigClass(final String configClass) {
+ this.configClass.set(configClass);
+ }
+
+ /**
+ * Registers a file with this builder.
+ * @param file The file to register.
+ */
+ void withFile(final String file) {
+ this.files.add(file);
+ }
+
+ /**
+ * Removes a file if it is registered with this builder, otherwise does nothing.
+ * @param file The file to remove.
+ */
+ void withoutFile(final String file) {
+ files.remove(file);
+ }
+
+ /**
+ * Removes all files that are registered with this builder.
+ */
+ void clearFiles() {
+ files.clear();
+ }
+
+ /**
+ * Registers an archive with this builder.
+ * @param archive The archive to register.
+ */
+ void withArchive(final String archive) {
+ this.archives.add(archive);
+ }
+
+ /**
+ * Removes an archive if it is registered with this builder, otherwise does nothing.
+ * @param archive The archive to remove.
+ */
+ void withoutArchive(final String archive) {
+ archives.remove(archive);
+ }
+
+ /**
+ * Removes all archives that are registered with this builder.
+ */
+ void clearArchives() {
+ archives.clear();
+ }
+
+ /**
+ * Registers a {@link Delete} object with this builder.
+ * @param delete The {@link Delete} object to register.
+ */
+ void withDelete(final Delete delete) {
+ this.deletes.add(delete);
+ }
+
+ /**
+ * Removes a {@link Delete} object if it is registered with this builder, otherwise does nothing.
+ * @param delete The {@link Delete} object to remove.
+ */
+ void withoutDelete(final Delete delete) {
+ deletes.remove(delete);
+ }
+
+ /**
+ * Removes all {@link Delete} objects that are registered with this builder.
+ */
+ void clearDeletes() {
+ deletes.clear();
+ }
+
+ /**
+ * Registers a {@link Mkdir} object with this builder.
+ * @param mkdir The {@link Mkdir} object to register.
+ */
+ void withMkdir(final Mkdir mkdir) {
+ this.mkdirs.add(mkdir);
+ }
+
+ /**
+ * Removes a {@link Mkdir} object if it is registered with this builder, otherwise does nothing.
+ * @param mkdir The {@link Mkdir} object to remove.
+ */
+ void withoutMkdir(final Mkdir mkdir) {
+ mkdirs.remove(mkdir);
+ }
+
+ /**
+ * Removes all {@link Mkdir} objects that are registered with this builder.
+ */
+ void clearMkdirs() {
+ mkdirs.clear();
+ }
+
+ /**
+ * Registers a {@link Move} object with this builder.
+ * @param move The {@link Move} object to register.
+ */
+ void withMove(final Move move) {
+ this.moves.add(move);
+ }
+
+ /**
+ * Removes a {@link Move} object if it is registered with this builder, otherwise does nothing.
+ * @param move The {@link Move} object to remove.
+ */
+ void withoutMove(final Move move) {
+ moves.remove(move);
+ }
+
+ /**
+ * Removes all {@link Move} objects that are registered with this builder.
+ */
+ void clearMoves() {
+ moves.clear();
+ }
+
+ /**
+ * Registers a {@link Chmod} object with this builder.
+ * @param chmod The {@link Chmod} object to register.
+ */
+ void withChmod(final Chmod chmod) {
+ this.chmods.add(chmod);
+ }
+
+ /**
+ * Removes a {@link Chmod} object if it is registered with this builder, otherwise does nothing.
+ * @param chmod The {@link Chmod} object to remove.
+ */
+ void withoutChmod(final Chmod chmod) {
+ chmods.remove(chmod);
+ }
+
+ /**
+ * Removes all {@link Chmod} objects that are registered with this builder.
+ */
+ void clearChmods() {
+ chmods.clear();
+ }
+
+ /**
+ * Registers a {@link Touchz} object with this builder.
+ * @param touchz The {@link Touchz} object to register.
+ */
+ void withTouchz(final Touchz touchz) {
+ this.touchzs.add(touchz);
+ }
+
+ /**
+ * Removes a {@link Touchz} object if it is registered with this builder, otherwise does nothing.
+ * @param touchz The {@link Touchz} object to remove.
+ */
+ void withoutTouchz(final Touchz touchz) {
+ touchzs.remove(touchz);
+ }
+
+ /**
+ * Removes all {@link Touchz} objects that are registered with this builder.
+ */
+ void clearTouchzs() {
+ touchzs.clear();
+ }
+
+ /**
+ * Registers a {@link Chgrp} object with this builder.
+ * @param chgrp The {@link Chgrp} object to register.
+ */
+ void withChgrp(final Chgrp chgrp) {
+ this.chgrps.add(chgrp);
+ }
+
+ /**
+ * Removes a {@link Chgrp} object if it is registered with this builder, otherwise does nothing.
+ * @param chgrp The {@link Chgrp} object to remove.
+ */
+ void withoutChgrp(final Chgrp chgrp) {
+ chgrps.remove(chgrp);
+ }
+
+ /**
+ * Removes all {@link Chgrp} objects that are registered with this builder.
+ */
+ void clearChgrps() {
+ chgrps.clear();
+ }
+
+ void withJavaOpts(final String javaOpts) {
+ this.javaOpts.set(javaOpts);
+ }
+
+ void withArg(final String arg) {
+ this.args.add(arg);
+ }
+
+ void withoutArg(final String arg) {
+ this.args.remove(arg);
+ }
+
+ void clearArgs() {
+ args.clear();
+ }
+
+ public void withLauncher(final Launcher launcher) {
+ this.launcher.set(launcher);
+ }
+
+ void withCaptureOutput(final Boolean captureOutput) {
+ this.captureOutput.set(captureOutput);
+ }
+
+ /**
+ * Creates a new {@link ActionAttributes} object with the properties stores in this builder.
+ * The new {@link ActionAttributes} object is independent of this builder and the builder can be used to build
+ * new instances.
+ * @return A new {@link ActionAttributes} object with the propertied stores in this builder.
+ */
+ public ActionAttributes build() {
+ return new ActionAttributes(
+ resourceManager.get(),
+ nameNode.get(),
+ prepare.get(),
+ streaming.get(),
+ pipes.get(),
+ ImmutableList.copyOf(jobXmls),
+ convertToConfigurationMap(configuration),
+ configClass.get(),
+ ImmutableList.copyOf(files),
+ ImmutableList.copyOf(archives),
+ ImmutableList.copyOf(deletes),
+ ImmutableList.copyOf(mkdirs),
+ ImmutableList.copyOf(moves),
+ ImmutableList.copyOf(chmods),
+ ImmutableList.copyOf(touchzs),
+ ImmutableList.copyOf(chgrps),
+ javaOpts.get(),
+ ImmutableList.copyOf(args),
+ launcher.get(),
+ captureOutput.get());
+ }
+
+ static Map<String, ModifyOnce<String>> convertToModifyOnceMap(final Map<String, String> configurationMap) {
+ final Map<String, ModifyOnce<String>> modifyOnceEntries = new LinkedHashMap<>();
+
+ for (final Map.Entry<String, String> keyAndValue : configurationMap.entrySet()) {
+ modifyOnceEntries.put(keyAndValue.getKey(), new ModifyOnce<>(keyAndValue.getValue()));
+ }
+
+ return modifyOnceEntries;
+ }
+
+ static ImmutableMap<String, String> convertToConfigurationMap(final Map<String, ModifyOnce<String>> map) {
+ final Map<String, String> mutableConfiguration = new LinkedHashMap<>();
+
+ for (final Map.Entry<String, ModifyOnce<String>> modifyOnceEntry : map.entrySet()) {
+ if (modifyOnceEntry.getValue().get() != null) {
+ mutableConfiguration.put(modifyOnceEntry.getKey(), modifyOnceEntry.getValue().get());
+ }
+ }
+
+ return ImmutableMap.copyOf(mutableConfiguration);
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Builder.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Builder.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Builder.java
new file mode 100644
index 0000000..c71a04b
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Builder.java
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+/**
+ * A common interface for builders.
+ * @param <T> The type of the object that is build using this builder.
+ */
+public interface Builder<T> {
+ /**
+ * Builds and returns an object.
+ * @return The built object.
+ */
+ T build();
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChFSBase.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChFSBase.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChFSBase.java
new file mode 100644
index 0000000..2fc1ff6
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChFSBase.java
@@ -0,0 +1,81 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * A base class for {@link Chgrp} and {@link Chmod}.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class ChFSBase {
+ private final boolean recursive;
+ private final String path;
+ private final String dirFiles;
+
+ ChFSBase(final ConstructionData constructionData) {
+ this.recursive = constructionData.recursive;
+ this.path = constructionData.path;
+ this.dirFiles = constructionData.dirFiles;
+ }
+
+ /**
+ * Returns whether this file system operation is recursive.
+ * @return {@code true} if this file system operation is recursive; {@code false} otherwise.
+ */
+ public boolean isRecursive() {
+ return recursive;
+ }
+
+ /**
+ * Returns the path of the target of this file system operation.
+ * @return The path of the target of this file system operation.
+ */
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * Returns whether this file system operation should be applied to all files in the given directory.
+ * @return "true" if this file system operation should be applied to all files in the given directory;
+ * "false" otherwise.
+ */
+ public String getDirFiles() {
+ return dirFiles;
+ }
+
+ /**
+ * Helper class that is used by the subclasses of this class and their builders.
+ */
+ public static class ConstructionData {
+ private final boolean recursive;
+ private final String path;
+ private final String dirFiles;
+
+ public ConstructionData(final boolean recursive,
+ final String path,
+ final String dirFiles) {
+ this.recursive = recursive;
+ this.path = path;
+ this.dirFiles = dirFiles;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChFSBaseBuilder.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChFSBaseBuilder.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChFSBaseBuilder.java
new file mode 100644
index 0000000..d1303ac
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChFSBaseBuilder.java
@@ -0,0 +1,95 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.oozie.fluentjob.api.ModifyOnce;
+
+/**
+ * A base class for {@link ChgrpBuilder} and {@link ChmodBuilder}.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public abstract class ChFSBaseBuilder <B extends ChFSBaseBuilder<B>> {
+ private final ModifyOnce<Boolean> recursive;
+ private final ModifyOnce<String> path;
+ private final ModifyOnce<String> dirFiles;
+
+ public ChFSBaseBuilder() {
+ recursive = new ModifyOnce<>(false);
+ path = new ModifyOnce<>();
+ dirFiles = new ModifyOnce<>("true");
+ }
+
+ /**
+ * Sets this file system operation to be recursive.
+ * @return This builder.
+ */
+ public B setRecursive() {
+ this.recursive.set(true);
+ return ensureRuntimeSelfReference();
+ }
+
+ /**
+ * Sets this file system operation to be non-recursive.
+ * @return This builder.
+ */
+ public B setNonRecursive() {
+ this.recursive.set(false);
+ return ensureRuntimeSelfReference();
+ }
+
+ /**
+ * Sets the path of the target of this file system operation.
+ * @param path the path of the target
+ * @return This builder.
+ */
+ public B withPath(final String path) {
+ this.path.set(path);
+ return ensureRuntimeSelfReference();
+ }
+
+ /**
+ * Sets whether this file system operation should be applied to all files in the given directory.
+ * @param dirFiles {@code true} if the operation should be applied to all files in the given directory;
+ * {@code false} if it shouldn't.
+ * @return This builder.
+ */
+ public B setDirFiles(final boolean dirFiles) {
+ this.dirFiles.set(Boolean.toString(dirFiles));
+ return ensureRuntimeSelfReference();
+ }
+
+ final B ensureRuntimeSelfReference() {
+ final B concrete = getRuntimeSelfReference();
+ if (concrete != this) {
+ throw new IllegalStateException(
+ "The builder type B doesn't extend ChFSBaseBuilder<B>.");
+ }
+
+ return concrete;
+ }
+
+ protected ChFSBase.ConstructionData getConstructionData() {
+ return new ChFSBase.ConstructionData(recursive.get(), path.get(), dirFiles.get());
+ }
+
+ protected abstract B getRuntimeSelfReference();
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Chgrp.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Chgrp.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Chgrp.java
new file mode 100644
index 0000000..1fa77eb
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Chgrp.java
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * A class representing the chgrp command of {@link FSAction}.
+ * Instances of this class should be built using the builder {@link ChgrpBuilder}.
+ *
+ * The properties of the builder can only be set once, an attempt to set them a second time will trigger
+ * an {@link IllegalStateException}.
+ *
+ * Builder instances can be used to build several elements, although properties already set cannot be changed after
+ * a call to {@link ChgrpBuilder#build} either.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class Chgrp extends ChFSBase {
+ private String group;
+
+ Chgrp(final ChFSBase.ConstructionData constructionData,
+ final String group) {
+ super(constructionData);
+ this.group = group;
+ }
+
+
+ /**
+ * Returns the new group that will be set by the command.
+ * @return The new group that will be set by the command.
+ */
+ public String getGroup() {
+ return group;
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChgrpBuilder.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChgrpBuilder.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChgrpBuilder.java
new file mode 100644
index 0000000..05cbe9b
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChgrpBuilder.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.oozie.fluentjob.api.ModifyOnce;
+
+/**
+ * A builder class for {@link Chgrp}.
+ *
+ * The properties of the builder can only be set once, an attempt to set them a second time will trigger
+ * an {@link IllegalStateException}. The properties that are lists are an exception to this rule, of course multiple
+ * elements can be added / removed.
+ *
+ * Builder instances can be used to build several elements, although properties already set cannot be changed after
+ * a call to {@link ChgrpBuilder#build} either.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class ChgrpBuilder extends ChFSBaseBuilder<ChgrpBuilder> implements Builder<Chgrp> {
+ private final ModifyOnce<String> group;
+
+ public ChgrpBuilder() {
+ this.group = new ModifyOnce<>();
+ }
+
+ /**
+ * Sets the new group that will be set by the operation.
+ * @param group The group that will be set by the operation.
+ * @return This builder.
+ */
+ public ChgrpBuilder withGroup(final String group) {
+ this.group.set(group);
+ return this;
+ }
+
+ /**
+ * Builds and returns a new {@link Chgrp} object with the properties set in this builder.
+ * The new {@link Chgrp} object is independent of this builder and the builder can be used to build new instances.
+ * @return The newly built {@link Chgrp} object.
+ */
+ @Override
+ public Chgrp build() {
+ return new Chgrp(getConstructionData(), group.get());
+ }
+
+ @Override
+ protected ChgrpBuilder getRuntimeSelfReference() {
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Chmod.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Chmod.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Chmod.java
new file mode 100644
index 0000000..b0e998b
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Chmod.java
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * A class representing the chmod command of {@link FSAction}.
+ * Instances of this class should be built using the builder {@link ChmodBuilder}.
+ *
+ * The properties of the builder can only be set once, an attempt to set them a second time will trigger
+ * an {@link IllegalStateException}.
+ *
+ * Builder instances can be used to build several elements, although properties already set cannot be changed after
+ * a call to {@link ChmodBuilder#build} either.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class Chmod extends ChFSBase {
+ private final String permissions;
+
+ Chmod(final ChFSBase.ConstructionData constructionData,
+ final String permissions) {
+ super(constructionData);
+ this.permissions = permissions;
+ }
+
+ /**
+ * Returns the new permissions that will be set by the command.
+ * @return The new permissions that will be set by the command.
+ */
+ public String getPermissions() {
+ return permissions;
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChmodBuilder.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChmodBuilder.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChmodBuilder.java
new file mode 100644
index 0000000..a6b439a
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ChmodBuilder.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.oozie.fluentjob.api.ModifyOnce;
+
+/**
+ * A builder class for {@link Chmod}.
+ *
+ * The properties of the builder can only be set once, an attempt to set them a second time will trigger
+ * an {@link IllegalStateException}. The properties that are lists are an exception to this rule, of course multiple
+ * elements can be added / removed.
+ *
+ * Builder instances can be used to build several elements, although properties already set cannot be changed after
+ * a call to {@link ChmodBuilder#build} either.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class ChmodBuilder extends ChFSBaseBuilder<ChmodBuilder> implements Builder<Chmod> {
+ private final ModifyOnce<String> permissions;
+
+ public ChmodBuilder() {
+ super();
+ permissions = new ModifyOnce<>();
+ }
+
+ /**
+ * Sets the new permissions that will be set by the operation.
+ * @param permissions The new permissions that will be set by the operation.
+ * @return This builder.
+ */
+ public ChmodBuilder withPermissions(final String permissions) {
+ this.permissions.set(permissions);
+ return this;
+ }
+
+ /**
+ * Builds and returns a new {@link Chmod} object with the properties set in this builder.
+ * The new {@link Chmod} object is independent of this builder and the builder can be used to build new instances.
+ * @return The newly built {@link Chmod} object.
+ */
+ public Chmod build() {
+ return new Chmod(getConstructionData(), permissions.get());
+ }
+
+ @Override
+ protected ChmodBuilder getRuntimeSelfReference() {
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Delete.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Delete.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Delete.java
new file mode 100644
index 0000000..17aab7f
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/Delete.java
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * A class representing the delete operation of {@link FSAction} and the prepare section of other actions.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class Delete {
+ private final String path;
+ private final Boolean skipTrash;
+
+ /**
+ * Creates a new {@link Delete} object.
+ * @param path The path of the file or directory to be deleted.
+ * @param skipTrash {@code true} if the deleted items should NOT be moved to the trash but deleted completely;
+ * {@code false} if the items should be moved to trash instead of deleting them conpletely.
+ */
+ public Delete(final String path, final Boolean skipTrash) {
+ this.path = path;
+ this.skipTrash = skipTrash;
+ }
+
+ /**
+ * Returns the path of the item to be deleted.
+ * @return The path of the item to be deleted.
+ */
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * Returns whether the trash should be skipped when deleting the items.
+ * @return {@code true} if the deleted items should NOT be moved to the trash but deleted completely;
+ * {@code false} if the items should be moved to trash instead of deleting them conpletely.
+ */
+ public Boolean getSkipTrash() {
+ return skipTrash;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/DistcpAction.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/DistcpAction.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/DistcpAction.java
new file mode 100644
index 0000000..3886af6
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/DistcpAction.java
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Represents the Oozie DistCp action.
+ * Instances of this class should be built using the builder {@link DistcpActionBuilder}.
+ *
+ * The properties of the builder can only be set once, an attempt to set them a second time will trigger
+ * an {@link IllegalStateException}.
+ *
+ * Builder instances can be used to build several elements, although properties already set cannot be changed after
+ * a call to {@link DistcpActionBuilder#build} either.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class DistcpAction extends Node implements HasAttributes {
+ private final ActionAttributes attributes;
+
+ DistcpAction(final ConstructionData constructionData,
+ final ActionAttributes attributes) {
+ super(constructionData);
+
+ this.attributes = attributes;
+ }
+
+ public String getResourceManager() {
+ return attributes.getResourceManager();
+ }
+
+ public String getNameNode() {
+ return attributes.getNameNode();
+ }
+
+ public Prepare getPrepare() {
+ return attributes.getPrepare();
+ }
+
+ public String getConfigProperty(final String property) {
+ return attributes.getConfiguration().get(property);
+ }
+
+ public Map<String, String> getConfiguration() {
+ return attributes.getConfiguration();
+ }
+
+ public String getJavaOpts() {
+ return attributes.getJavaOpts();
+ }
+
+ public List<String> getArgs() {
+ return attributes.getArgs();
+ }
+
+ public ActionAttributes getAttributes() {
+ return attributes;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/DistcpActionBuilder.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/DistcpActionBuilder.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/DistcpActionBuilder.java
new file mode 100644
index 0000000..42731ef
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/DistcpActionBuilder.java
@@ -0,0 +1,118 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * A builder class for {@link DistcpAction}.
+ *
+ * The properties of the builder can only be set once, an attempt to set them a second time will trigger
+ * an {@link IllegalStateException}. The properties that are lists are an exception to this rule, of course multiple
+ * elements can be added / removed.
+ *
+ * Builder instances can be used to build several elements, although properties already set cannot be changed after
+ * a call to {@link DistcpActionBuilder#build} either.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class DistcpActionBuilder extends NodeBuilderBaseImpl<DistcpActionBuilder> implements Builder<DistcpAction> {
+ private final ActionAttributesBuilder attributesBuilder;
+
+ public static DistcpActionBuilder create() {
+ final ActionAttributesBuilder builder = ActionAttributesBuilder.create();
+
+ return new DistcpActionBuilder(
+ null,
+ builder);
+ }
+
+ public static DistcpActionBuilder createFromExistingAction(final Node action) {
+ final ActionAttributesBuilder builder = ActionAttributesBuilder.createFromAction(action);
+
+ return new DistcpActionBuilder(action,
+ builder);
+ }
+
+ DistcpActionBuilder(final Node action,
+ final ActionAttributesBuilder attributesBuilder) {
+ super(action);
+
+ this.attributesBuilder = attributesBuilder;
+ }
+
+ public DistcpActionBuilder withResourceManager(final String resourceManager) {
+ attributesBuilder.withResourceManager(resourceManager);
+ return this;
+ }
+
+ public DistcpActionBuilder withNameNode(final String nameNode) {
+ attributesBuilder.withNameNode(nameNode);
+ return this;
+ }
+
+ public DistcpActionBuilder withPrepare(final Prepare prepare) {
+ attributesBuilder.withPrepare(prepare);
+ return this;
+ }
+
+ public DistcpActionBuilder withConfigProperty(final String key, final String value) {
+ attributesBuilder.withConfigProperty(key, value);
+ return this;
+ }
+
+ public DistcpActionBuilder withJavaOpts(final String javaOpts) {
+ attributesBuilder.withJavaOpts(javaOpts);
+ return this;
+ }
+
+ public DistcpActionBuilder withArg(final String arg) {
+ attributesBuilder.withArg(arg);
+ return this;
+ }
+
+ public DistcpActionBuilder withoutArg(final String arg) {
+ attributesBuilder.withoutArg(arg);
+ return this;
+ }
+
+ public DistcpActionBuilder clearArgs() {
+ attributesBuilder.clearArgs();
+ return this;
+ }
+
+ @Override
+ public DistcpAction build() {
+ final Node.ConstructionData constructionData = getConstructionData();
+
+ final DistcpAction instance = new DistcpAction(
+ constructionData,
+ attributesBuilder.build());
+
+ addAsChildToAllParents(instance);
+
+ return instance;
+ }
+
+ @Override
+ protected DistcpActionBuilder getRuntimeSelfReference() {
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/EmailAction.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/EmailAction.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/EmailAction.java
new file mode 100644
index 0000000..bbaecbc
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/EmailAction.java
@@ -0,0 +1,118 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * A class representing the Oozie email action.
+ * Instances of this class should be built using the builder {@link EmailActionBuilder}.
+ *
+ * The properties of the builder can only be set once, an attempt to set them a second time will trigger
+ * an {@link IllegalStateException}.
+ *
+ * Builder instances can be used to build several elements, although properties already set cannot be changed after
+ * a call to {@link EmailActionBuilder#build} either.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class EmailAction extends Node {
+ private final String to;
+ private final String cc;
+ private final String bcc;
+ private final String subject;
+ private final String body;
+ private final String contentType;
+ private final String attachment;
+
+ EmailAction(final Node.ConstructionData constructionData,
+ final String to,
+ final String cc,
+ final String bcc,
+ final String subject,
+ final String body,
+ final String contentType,
+ final String attachment) {
+ super(constructionData);
+ this.to = to;
+ this.cc = cc;
+ this.bcc = bcc;
+ this.subject = subject;
+ this.body = body;
+ this.contentType = contentType;
+ this.attachment = attachment;
+ }
+
+ /**
+ * Returns the address of the recipient of the email.
+ * @return The address of the recipient of the email.
+ */
+ public String getRecipient() {
+ return to;
+ }
+
+ /**
+ * Returns the address of the recipient of a copy of the email.
+ * @return The address of the recipient of a copy of the email.
+ */
+ public String getCc() {
+ return cc;
+ }
+
+ /**
+ * Returns the address of the secret recipient of a copy of the email.
+ * @return The address of the secret recipient of a copy of the email.
+ */
+ public String getBcc() {
+ return bcc;
+ }
+
+ /**
+ * Returns the subject of the email.
+ * @return The subject of the email.
+ */
+ public String getSubject() {
+ return subject;
+ }
+
+ /**
+ * Returns the body of the email.
+ * @return The body of the email.
+ */
+ public String getBody() {
+ return body;
+ }
+
+ /**
+ * Returns the content type of the email.
+ * @return The content type of the email.
+ */
+ public String getContentType() {
+ return contentType;
+ }
+
+ /**
+ * Returns the attachment of the email.
+ * @return The attachment of the email.
+ */
+ public String getAttachment() {
+ return attachment;
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/EmailActionBuilder.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/EmailActionBuilder.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/EmailActionBuilder.java
new file mode 100644
index 0000000..fb78f97
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/EmailActionBuilder.java
@@ -0,0 +1,234 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.oozie.fluentjob.api.ModifyOnce;
+
+/**
+ * A builder class for {@link EmailAction}.
+ * <p>
+ * The properties of the builder can only be set once, an attempt to set them a second time will trigger
+ * an {@link IllegalStateException}. The properties that are lists are an exception to this rule, of course multiple
+ * elements can be added / removed.
+ * <p>
+ * Builder instances can be used to build several elements, although properties already set cannot be changed after
+ * a call to {@link EmailActionBuilder#build} either.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class EmailActionBuilder extends NodeBuilderBaseImpl<EmailActionBuilder> implements Builder<EmailAction> {
+ private final ModifyOnce<String> to;
+ private final ModifyOnce<String> cc;
+ private final ModifyOnce<String> bcc;
+ private final ModifyOnce<String> subject;
+ private final ModifyOnce<String> body;
+ private final ModifyOnce<String> contentType;
+ private final ModifyOnce<String> attachment;
+
+ /**
+ * Creates and returns an empty builder.
+ * @return An empty builder.
+ */
+ public static EmailActionBuilder create() {
+ final ModifyOnce<String> to = new ModifyOnce<>();
+ final ModifyOnce<String> cc = new ModifyOnce<>();
+ final ModifyOnce<String> bcc = new ModifyOnce<>();
+ final ModifyOnce<String> subject = new ModifyOnce<>();
+ final ModifyOnce<String> body = new ModifyOnce<>();
+ final ModifyOnce<String> contentType = new ModifyOnce<>();
+ final ModifyOnce<String> attachment = new ModifyOnce<>();
+
+ return new EmailActionBuilder(
+ null,
+ to,
+ cc,
+ bcc,
+ subject,
+ body,
+ contentType,
+ attachment);
+ }
+
+ /**
+ * Create and return a new {@link EmailActionBuilder} that is based on an already built
+ * {@link EmailAction} object. The properties of the builder will initially be the same as those of the
+ * provided {@link EmailAction} object, but it is possible to modify them once.
+ * @param action The {@link EmailAction} object on which this {@link EmailActionBuilder} will be based.
+ * @return A new {@link EmailActionBuilder} that is based on a previously built {@link EmailAction} object.
+ */
+ public static EmailActionBuilder createFromExistingAction(final EmailAction action) {
+ final ModifyOnce<String> to = new ModifyOnce<>(action.getRecipient());
+ final ModifyOnce<String> cc = new ModifyOnce<>(action.getCc());
+ final ModifyOnce<String> bcc = new ModifyOnce<>(action.getBcc());
+ final ModifyOnce<String> subject = new ModifyOnce<>(action.getSubject());
+ final ModifyOnce<String> body = new ModifyOnce<>(action.getBody());
+ final ModifyOnce<String> contentType = new ModifyOnce<>(action.getContentType());
+ final ModifyOnce<String> attachment = new ModifyOnce<>(action.getAttachment());
+
+ return new EmailActionBuilder(
+ action,
+ to,
+ cc,
+ bcc,
+ subject,
+ body,
+ contentType,
+ attachment);
+ }
+
+ public static EmailActionBuilder createFromExistingAction(final Node action) {
+ final ModifyOnce<String> to = new ModifyOnce<>();
+ final ModifyOnce<String> cc = new ModifyOnce<>();
+ final ModifyOnce<String> bcc = new ModifyOnce<>();
+ final ModifyOnce<String> subject = new ModifyOnce<>();
+ final ModifyOnce<String> body = new ModifyOnce<>();
+ final ModifyOnce<String> contentType = new ModifyOnce<>();
+ final ModifyOnce<String> attachment = new ModifyOnce<>();
+
+ return new EmailActionBuilder(
+ action,
+ to,
+ cc,
+ bcc,
+ subject,
+ body,
+ contentType,
+ attachment);
+ }
+
+ EmailActionBuilder(final Node action,
+ final ModifyOnce<String> to,
+ final ModifyOnce<String> cc,
+ final ModifyOnce<String> bcc,
+ final ModifyOnce<String> subject,
+ final ModifyOnce<String> body,
+ final ModifyOnce<String> contentType,
+ final ModifyOnce<String> attachment) {
+ super(action);
+ this.to = to;
+ this.cc = cc;
+ this.bcc = bcc;
+ this.subject = subject;
+ this.body = body;
+ this.contentType = contentType;
+ this.attachment = attachment;
+ }
+
+ /**
+ * Sets the address of the recipient of the email.
+ * @param to the recipient in To: field
+ * @return This builder.
+ */
+ public EmailActionBuilder withRecipient(final String to) {
+ this.to.set(to);
+ return this;
+ }
+
+ /**
+ * Sets the address of the recipient of a copy of the email.
+ * @param cc the recipient in CC: field
+ * @return This builder.
+ */
+ public EmailActionBuilder withCc(final String cc) {
+ this.cc.set(cc);
+ return this;
+ }
+
+ /**
+ * Sets the address of the secret recipient of a copy of the email.
+ * @param bcc the recipient in BCC: field
+ * @return This builder.
+ */
+ public EmailActionBuilder withBcc(final String bcc) {
+ this.bcc.set(bcc);
+ return this;
+ }
+
+ /**
+ * Sets the subject of the email.
+ * @param subject the email subject
+ * @return This builder.
+ */
+ public EmailActionBuilder withSubject(final String subject) {
+ this.subject.set(subject);
+ return this;
+ }
+
+ /**
+ * Sets the body of the email.
+ * @param body the email body
+ * @return This builder.
+ */
+ public EmailActionBuilder withBody(final String body) {
+ this.body.set(body);
+ return this;
+ }
+
+ /**
+ * Sets the content type of the email.
+ * @param contentType the email content type
+ * @return This builder
+ */
+ public EmailActionBuilder withContentType(final String contentType) {
+ this.contentType.set(contentType);
+ return this;
+ }
+
+ /**
+ * Sets the attachment of the email.
+ * @param attachment the email attachment path
+ * @return This builder.
+ */
+ public EmailActionBuilder withAttachment(final String attachment) {
+ this.attachment.set(attachment);
+ return this;
+ }
+
+ /**
+ * Creates a new {@link EmailAction} object with the properties stores in this builder.
+ * The new {@link EmailAction} object is independent of this builder and the builder can be used to build
+ * new instances.
+ * @return A new {@link EmailAction} object with the properties stored in this builder.
+ */
+ @Override
+ public EmailAction build() {
+ final Node.ConstructionData constructionData = getConstructionData();
+
+ final EmailAction instance = new EmailAction(
+ constructionData,
+ to.get(),
+ cc.get(),
+ bcc.get(),
+ subject.get(),
+ body.get(),
+ contentType.get(),
+ attachment.get());
+
+ addAsChildToAllParents(instance);
+
+ return instance;
+ }
+
+ @Override
+ protected EmailActionBuilder getRuntimeSelfReference() {
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ErrorHandler.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ErrorHandler.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ErrorHandler.java
new file mode 100644
index 0000000..6129b9f
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/ErrorHandler.java
@@ -0,0 +1,78 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import com.google.common.base.Preconditions;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * A class encapsulating an action so that it can be used as an error handler in a workflow.
+ *
+ * In an Oozie workflow definition (XML), every action has an "ok-transition" that is taken if the action completed
+ * successfully and an "error-transition" that is taken if the action failed. In this API, the dependency relations
+ * specified will be translated into "ok-transitions".
+ *
+ * If you would like to provide some error handling in case of action failure, you should add an {@link ErrorHandler}
+ * to the {@link Node} representing the action. The error handler action will be added as the "error-transition" of
+ * the original action in the generated Oozie workflow XML. Both the "ok-transition" and the "error-transition" of the
+ * error handler action itself will lead to an autogenerated kill node.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class ErrorHandler {
+ private final Node handlerNode;
+
+ /**
+ * Creates a new {@link ErrorHandler}. The provided builder is used to build the underlying error handler action.
+ * The builder should be in a state where no parents are specified, otherwise an exception is thrown.
+ * @param builder The builder that is used to build the underlying error handler node.
+ * @return A new {@link ErrorHandler}.
+ *
+ * @throws IllegalStateException if the provided builder has parents registered.
+ */
+ public static ErrorHandler buildAsErrorHandler(final Builder<? extends Node> builder) {
+ final Node handlerNode = builder.build();
+ return new ErrorHandler(handlerNode);
+ }
+
+ private ErrorHandler(final Node handlerNode) {
+ final boolean hasParents = !handlerNode.getAllParents().isEmpty();
+ final boolean hasChildren = !handlerNode.getAllChildren().isEmpty();
+ Preconditions.checkState(!hasParents && !hasChildren, "Error handler nodes cannot have parents or children.");
+
+ this.handlerNode = handlerNode;
+ }
+
+ /**
+ * Returns the name of the error handler action.
+ * @return The name of the error handler action.
+ */
+ public String getName() {
+ return handlerNode.getName();
+ }
+
+ /**
+ * Returns the error handler action node.
+ * @return The error handler action node.
+ */
+ public Node getHandlerNode() {
+ return handlerNode;
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/FSAction.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/FSAction.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/FSAction.java
new file mode 100644
index 0000000..5d10e80
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/FSAction.java
@@ -0,0 +1,137 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A class representing the Oozie file system action.
+ * Instances of this class should be built using the builder {@link FSActionBuilder}.
+ *
+ * The properties of the builder can only be set once, an attempt to set them a second time will trigger
+ * an {@link IllegalStateException}.
+ *
+ * Builder instances can be used to build several elements, although properties already set cannot be changed after
+ * a call to {@link FSActionBuilder#build} either.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class FSAction extends Node implements HasAttributes {
+ private final ActionAttributes attributes;
+
+ FSAction(final Node.ConstructionData constructionData,
+ final ActionAttributes attributes) {
+ super(constructionData);
+
+ this.attributes = attributes;
+ }
+
+ /**
+ * Returns the name node used by this {@link FSAction}.
+ * @return The name node used by this {@link FSAction}.
+ */
+ public String getNameNode() {
+ return attributes.getNameNode();
+ }
+
+ /**
+ * Returns the list of job XMLs used by this {@link FSAction}.
+ * @return The list of job XMLs used by this {@link FSAction}.
+ */
+ public List<String> getJobXmls() {
+ return attributes.getJobXmls();
+ }
+
+ /**
+ * Returns the value associated with the provided configuration property name.
+ * @param property The name of the configuration property for which the value will be returned.
+ * @return The value associated with the provided configuration property name.
+ */
+ public String getConfigProperty(final String property) {
+ return attributes.getConfiguration().get(property);
+ }
+
+ /**
+ * Returns all configuration properties of this {@link FSAction} as a map.
+ * @return All configuration properties of this {@link FSAction} as a map.
+ */
+ public Map<String, String> getConfiguration() {
+ return attributes.getConfiguration();
+ }
+
+ /**
+ * Returns the {@link Delete} objects that specify which directories or files will be deleted when running this action.
+ * @return The {@link Delete} objects that specify which directories or files will be deleted when running this action.
+ */
+ public List<Delete> getDeletes() {
+ return attributes.getDeletes();
+ }
+
+ /**
+ * Returns the {@link Mkdir} objects that specify which directories will be created when running this action.
+ * @return The {@link Mkdir} objects that specify which directories will be created when running this action.
+ */
+ public List<Mkdir> getMkdirs() {
+ return attributes.getMkdirs();
+ }
+
+ /**
+ * Returns the {@link Move} objects that specify which directories or files will be moved and where when running this action.
+ * @return The {@link Move} objects that specify which directories or files will be moved and where when running this action.
+ */
+ public List<Move> getMoves() {
+ return attributes.getMoves();
+ }
+
+ /**
+ * Returns the {@link Chmod} objects that specify the directories or files the permission of which will be changed
+ * and to what when running this action.
+ * @return The {@link Chmod} objects that specify the directories or files the permission of which will be changed
+ * and to what when running this action.
+ */
+ public List<Chmod> getChmods() {
+ return attributes.getChmods();
+ }
+
+ /**
+ * Returns the {@link Touchz} objects that specify which files will be touched when running this action.
+ * @return The {@link Touchz} objects that specify which files will be touched when running this action.
+ */
+ public List<Touchz> getTouchzs() {
+ return attributes.getTouchzs();
+ }
+
+ /**
+ * Returns the {@link Chgrp} objects that specify the directories or files the owner / group of which will be changed
+ * and to what when running this action.
+ * @return The {@link Chgrp} objects that specify the directories or files the owner / group of which will be changed
+ * and to what when running this action.
+ */
+ public List<Chgrp> getChgrps() {
+ return attributes.getChgrps();
+ }
+
+ public ActionAttributes getAttributes() {
+ return attributes;
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/FSActionBuilder.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/FSActionBuilder.java b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/FSActionBuilder.java
new file mode 100644
index 0000000..e70b061
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/main/java/org/apache/oozie/fluentjob/api/action/FSActionBuilder.java
@@ -0,0 +1,323 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.oozie.fluentjob.api.action;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+
+/**
+ * A builder class for {@link FSAction}.
+ * <p>
+ * The properties of the builder can only be set once, an attempt to set them a second time will trigger
+ * an {@link IllegalStateException}. The properties that are lists are an exception to this rule, of course multiple
+ * elements can be added / removed.
+ * <p>
+ * Builder instances can be used to build several elements, although properties already set cannot be changed after
+ * a call to {@link FSActionBuilder#build} either.
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class FSActionBuilder extends NodeBuilderBaseImpl<FSActionBuilder> implements Builder<FSAction> {
+ private final ActionAttributesBuilder attributesBuilder;
+
+ /**
+ * Creates and returns an empty builder.
+ * @return An empty builder.
+ */
+ public static FSActionBuilder create() {
+ final ActionAttributesBuilder builder = ActionAttributesBuilder.create();
+
+ return new FSActionBuilder(
+ null,
+ builder);
+ }
+
+ /**
+ * Create and return a new {@link FSActionBuilder} that is based on an already built
+ * {@link FSAction} object. The properties of the builder will initially be the same as those of the
+ * provided {@link FSAction} object, but it is possible to modify them once.
+ * @param action The {@link FSAction} object on which this {@link FSActionBuilder} will be based.
+ * @return A new {@link FSActionBuilder} that is based on a previously built {@link FSAction} object.
+ */
+ public static FSActionBuilder createFromExistingAction(final Node action) {
+ final ActionAttributesBuilder builder = ActionAttributesBuilder.createFromAction(action);
+
+ return new FSActionBuilder(
+ action,
+ builder);
+ }
+
+ FSActionBuilder(final Node action,
+ final ActionAttributesBuilder attributesBuilder) {
+ super(action);
+
+ this.attributesBuilder = attributesBuilder;
+ }
+
+ /**
+ * Registers a name node.
+ * @param nameNode The string representing the name node.
+ * @return this
+ * @throws IllegalStateException if a name node has already been set on this builder.
+ */
+ public FSActionBuilder withNameNode(final String nameNode) {
+ attributesBuilder.withNameNode(nameNode);
+ return this;
+ }
+
+ /**
+ * Registers a job XML with this builder.
+ * @param jobXml The job XML to register.
+ * @return this
+ */
+ public FSActionBuilder withJobXml(final String jobXml) {
+ attributesBuilder.withJobXml(jobXml);
+ return this;
+ }
+
+ /**
+ * Removes a job XML if it is registered with this builder, otherwise does nothing.
+ * @param jobXml The job XML to remove.
+ * @return this
+ */
+ public FSActionBuilder withoutJobXml(final String jobXml) {
+ attributesBuilder.withoutJobXml(jobXml);
+ return this;
+ }
+
+ /**
+ * Removes all job XMLs that are registered with this builder.
+ * @return this
+ */
+ public FSActionBuilder clearJobXmls() {
+ attributesBuilder.clearJobXmls();
+ return this;
+ }
+
+ /**
+ * Registers a configuration property (a key-value pair) with this builder. If the provided key has already been
+ * set on this builder, an exception is thrown. Setting a key to null means deleting it.
+ * @param key The name of the property to set.
+ * @param value The value of the property to set.
+ * @return this
+ * @throws IllegalStateException if the provided key has already been set on this builder.
+ */
+ public FSActionBuilder withConfigProperty(final String key, final String value) {
+ attributesBuilder.withConfigProperty(key, value);
+ return this;
+ }
+
+ /**
+ * Registers a {@link Delete} object with this builder.
+ * @param delete The {@link Delete} object to register.
+ * @return this
+ */
+ public FSActionBuilder withDelete(final Delete delete) {
+ attributesBuilder.withDelete(delete);
+ return this;
+ }
+
+ /**
+ * Removes a {@link Delete} object if it is registered with this builder, otherwise does nothing.
+ * @param delete The {@link Delete} object to remove.
+ * @return this
+ */
+ public FSActionBuilder withoutDelete(final Delete delete) {
+ attributesBuilder.withoutDelete(delete);
+ return this;
+ }
+
+ /**
+ * Removes all {@link Delete} objects that are registered with this builder.
+ * @return this
+ */
+ public FSActionBuilder clearDeletes() {
+ attributesBuilder.clearDeletes();
+ return this;
+ }
+
+ /**
+ * Registers a {@link Mkdir} object with this builder.
+ * @param mkdir The {@link Mkdir} object to register.
+ * @return this
+ */
+ public FSActionBuilder withMkdir(final Mkdir mkdir) {
+ attributesBuilder.withMkdir(mkdir);
+ return this;
+ }
+
+ /**
+ * Removes a {@link Mkdir} object if it is registered with this builder, otherwise does nothing.
+ * @param mkdir The {@link Mkdir} object to remove.
+ * @return this
+ */
+ public FSActionBuilder withoutMkdir(final Mkdir mkdir) {
+ attributesBuilder.withoutMkdir(mkdir);
+ return this;
+ }
+
+ /**
+ * Removes all {@link Mkdir} objects that are registered with this builder.
+ * @return this
+ */
+ public FSActionBuilder clearMkdirs() {
+ attributesBuilder.clearMkdirs();
+ return this;
+ }
+
+ /**
+ * Registers a {@link Move} object with this builder.
+ * @param move The {@link Move} object to register.
+ * @return this
+ */
+ public FSActionBuilder withMove(final Move move) {
+ attributesBuilder.withMove(move);
+ return this;
+ }
+
+ /**
+ * Removes a {@link Move} object if it is registered with this builder, otherwise does nothing.
+ * @param move The {@link Move} object to remove.
+ * @return this
+ */
+ public FSActionBuilder withoutMove(final Move move) {
+ attributesBuilder.withoutMove(move);
+ return this;
+ }
+
+ /**
+ * Removes all {@link Move} objects that are registered with this builder.
+ * @return this
+ */
+ public FSActionBuilder clearMoves() {
+ attributesBuilder.clearMoves();
+ return this;
+ }
+
+ /**
+ * Registers a {@link Chmod} object with this builder.
+ * @param chmod The {@link Chmod} object to register.
+ * @return this
+ */
+ public FSActionBuilder withChmod(final Chmod chmod) {
+ attributesBuilder.withChmod(chmod);
+ return this;
+ }
+
+ /**
+ * Removes a {@link Chmod} object if it is registered with this builder, otherwise does nothing.
+ * @param chmod The {@link Chmod} object to remove.
+ * @return this
+ */
+ public FSActionBuilder withoutChmod(final Chmod chmod) {
+ attributesBuilder.withoutChmod(chmod);
+ return this;
+ }
+
+ /**
+ * Removes all {@link Chmod} objects that are registered with this builder.
+ * @return this
+ */
+ public FSActionBuilder clearChmods() {
+ attributesBuilder.clearChmods();
+ return this;
+ }
+
+ /**
+ * Registers a {@link Touchz} object with this builder.
+ * @param touchz The {@link Touchz} object to register.
+ * @return this
+ */
+ public FSActionBuilder withTouchz(final Touchz touchz) {
+ attributesBuilder.withTouchz(touchz);
+ return this;
+ }
+
+ /**
+ * Removes a {@link Touchz} object if it is registered with this builder, otherwise does nothing.
+ * @param touchz The {@link Touchz} object to remove.
+ * @return this
+ */
+ public FSActionBuilder withoutTouchz(final Touchz touchz) {
+ attributesBuilder.withoutTouchz(touchz);
+ return this;
+ }
+
+ /**
+ * Removes all {@link Touchz} objects that are registered with this builder.
+ * @return this
+ */
+ public FSActionBuilder clearTouchzs() {
+ attributesBuilder.clearTouchzs();
+ return this;
+ }
+
+ /**
+ * Registers a {@link Chgrp} object with this builder.
+ * @param chgrp The {@link Chgrp} object to register.
+ * @return this
+ */
+ public FSActionBuilder withChgrp(final Chgrp chgrp) {
+ attributesBuilder.withChgrp(chgrp);
+ return this;
+ }
+
+ /**
+ * Removes a {@link Chgrp} object if it is registered with this builder, otherwise does nothing.
+ * @param chgrp The {@link Chgrp} object to remove.
+ * @return this
+ */
+ public FSActionBuilder withoutChgrp(final Chgrp chgrp) {
+ attributesBuilder.withoutChgrp(chgrp);
+ return this;
+ }
+
+ /**
+ * Removes all {@link Chgrp} objects that are registered with this builder.
+ * @return this
+ */
+ public FSActionBuilder clearChgrps() {
+ attributesBuilder.clearChgrps();
+ return this;
+ }
+
+ /**
+ * Creates a new {@link FSAction} object with the properties stores in this builder.
+ * The new {@link FSAction} object is independent of this builder and the builder can be used to build
+ * new instances.
+ * @return A new {@link FSAction} object with the properties stored in this builder.
+ */
+ @Override
+ public FSAction build() {
+ final Node.ConstructionData constructionData = getConstructionData();
+
+ final FSAction instance = new FSAction(
+ constructionData,
+ attributesBuilder.build());
+
+ addAsChildToAllParents(instance);
+
+ return instance;
+ }
+
+ @Override
+ protected FSActionBuilder getRuntimeSelfReference() {
+ return this;
+ }
+}