Package org.linkedin.glu.provisioner.plan.api

Source Code of org.linkedin.glu.provisioner.plan.api.Plan

/*
* Copyright (c) 2010-2010 LinkedIn, Inc
* Portions Copyright (c) 2014 Yan Pujante
*
* Licensed 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.linkedin.glu.provisioner.plan.api;

import org.json.JSONException;
import org.json.JSONObject;
import org.linkedin.util.xml.XMLIndent;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.LinkedHashMap;

/**
* A plan is represented by the step to execute and the dependency graph (between leaves).
*
* @author ypujante@linkedin.com
*/
public class Plan<T>
{
  private final Map<String, Object> _metadata = new LinkedHashMap<String, Object>();
  private final IStep<T> _step;

  // cache
  private volatile Collection<LeafStep<T>> _leafSteps = null;

  /**
   * Constructor
   */
  public Plan(Map<String, Object> metadata, IStep<T> step)
  {
    if(metadata == null && step != null)
      metadata = step.getMetadata();
    if(metadata != null)
      _metadata.putAll(metadata);
    _step = step;
  }

  /**
   * Builds an empty plan
   */
  public Plan()
  {
    this(null, null);
  }

  /**
   * Constructor
   */
  public Plan(IStep<T> step)
  {
    this(step == null ? null : step.getMetadata(), step);
  }

  public void setMetadata(String name, Object value)
  {
    _metadata.put(name, value);
  }

  public Map<String, Object> getMetadata()
  {
    return _metadata;
  }

  public void setMetadata(Map<String, Object> metadata)
  {
    if(metadata != null)
    {
      _metadata.putAll(metadata);
    }
  }

  public String getName()
  {
    return (String) _metadata.get("name");
  }

  /**
   * Change the name of a plan
   */
  public void setName(String name)
  {
    _metadata.put("name", name);
  }

  /**
   * Change the name of a plan
   */
  public void setId(String id)
  {
    _metadata.put("id", id);
  }

  public String getId()
  {
    String id = (String) _metadata.get("id");

    if(id == null)
    {
      if(_step == null)
        id = Integer.toHexString(System.identityHashCode(this));
      else
        id = getStep().getId();
    }

    return id;
  }

  public IStep<T> getStep()
  {
    return _step;
  }

  /**
   * @return all the leaf steps of this plan.
   */
  public Collection<LeafStep<T>> getLeafSteps()
  {
    // implementation note: not synchronized on purpose. The variable is volatile so if 2 threads
    // happens to call this at the same time, they may compute the result twice but since the
    // object is immutable it is not an issue.
    if(_leafSteps == null)
    {
      _leafSteps = doGetLeafSteps();
    }
    return _leafSteps;
  }

  /**
   * @return all the leaf steps of this plan.
   */
  private Collection<LeafStep<T>> doGetLeafSteps()
  {
    final Collection<LeafStep<T>> leaves = new ArrayList<LeafStep<T>>();

    if(_step != null)
    {
      _step.acceptVisitor(new IStepVisitor<T>()
      {
        @Override
        public void startVisit()
        {
        }

        @Override
        public void visitLeafStep(LeafStep<T> tLeafStep)
        {
          leaves.add(tLeafStep);
        }

        @Override
        public IStepVisitor<T> visitSequentialStep(SequentialStep<T> tSequentialStep)
        {
          return this;
        }

        @Override
        public IStepVisitor<T> visitParallelStep(ParallelStep<T> parallelStep)
        {
          return this;
        }

        @Override
        public void endVisit()
        {
        }
      });
    }

    return leaves;
  }


  /**
   * @return <code>true</code> if this plan has any leaf step
   */
  public boolean hasLeafSteps()
  {
    return !getLeafSteps().isEmpty();
  }

  /**
   * @return the number of leaf steps
   */
  public int getLeafStepsCount()
  {
    return getLeafSteps().size();
  }

  /**
   * @return a plan builder representing this plan (usually used to do minor modifications to the
   *         plan, like adding some steps or removing some).
   */
  public IPlanBuilder<T> toPlanBuilder()
  {
    return toPlanBuilder(new IPlanBuilder.Config());
  }

  /**
   * @return a plan builder representing this plan (usually used to do minor modifications to the
   *         plan, like adding some steps or removing some).
   */
  public IPlanBuilder<T> toPlanBuilder(IPlanBuilder.Config config)
  {
    return toPlanBuilder(StepFilters.<T>acceptAll(), config);
  }

  /**
   * Same as {@link #toPlanBuilder(IPlanBuilder.Config)} except it also filters out unwanted steps.
   *
   * @param filter the filter to filter out unwanted steps
   * @return a new plan builder
   */
  public IPlanBuilder<T> toPlanBuilder(IStepFilter<T> filter)
  {
    return toPlanBuilder(filter, new IPlanBuilder.Config());
  }

  /**
   * Same as {@link #toPlanBuilder(IPlanBuilder.Config)} except it also filters out unwanted steps.
   *
   * @param filter the filter to filter out unwanted steps
   * @return a new plan builder
   */
  public IPlanBuilder<T> toPlanBuilder(IStepFilter<T> filter, IPlanBuilder.Config config)
  {
    PlanBuilder<T> builder = new PlanBuilder<T>(config);
    builder.setMetadata(_metadata);

    if(_step != null)
      _step.acceptVisitor(new CompositeStepBuilderVisitor<T>(builder, filter));

    return builder;
  }

  /**
   * @return an empty plan builder based of the dependencies in this plan.
   */
  public IPlanBuilder<T> createEmptyPlanBuilder()
  {
    return createEmptyPlanBuilder(new IPlanBuilder.Config());
  }

  /**
   * @return an empty plan builder based of the dependencies in this plan.
   */
  public IPlanBuilder<T> createEmptyPlanBuilder(IPlanBuilder.Config config)
  {
    return new PlanBuilder<T>(config);
  }

  /**
   * @return an xml representation of the plan
   */
  public String toXml()
  {
    return toXml(null);
  }

  /**
   * @return an xml representation of the plan
   */
  public String toXml(Map<String, Object> context)
  {
    XmlStepVisitor<T> visitor = new XmlStepVisitor<T>();

    XMLIndent xml = visitor.getXml();

    xml.addXMLDecl("1.0");

    Map<String, Object> attributes = new LinkedHashMap<String, Object>();
    attributes.putAll(_metadata);

    if(context != null)
    {
      attributes.putAll(context);
    }

    if(_step != null)
    {
      xml.addOpeningTag("plan", attributes);
      _step.acceptVisitor(visitor);
      xml.addClosingTag("plan");
    }
    else
    {
      xml.addEmptyTag("plan", attributes);
    }

    return xml.getXML();
  }

  public JSONObject toJson()
  {
    JSONObject json = new JSONObject();

    try
    {
      json.put("metadata", getMetadata());
      if(_step != null)
      {
        JsonStepVisitor<T> visitor = new JsonStepVisitor<T>(json);
        _step.acceptVisitor(visitor);
      }
    }
    catch(JSONException e)
    {
      throw new RuntimeException(e);
    }

    return json;
  }

  @Override
  public String toString()
  {
    return toXml();
  }
}
TOP

Related Classes of org.linkedin.glu.provisioner.plan.api.Plan

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.