text:
"""Import a trackable object from a SavedModel."""

import collections
import functools
import os
import sys

from tensorflow.core.protobuf import graph_debug_info_pb2
from tensorflow.python.checkpoint import checkpoint
from tensorflow.python.checkpoint import checkpoint_options
from tensorflow.python.checkpoint import graph_view
from tensorflow.python.checkpoint import restore
from tensorflow.python.distribute import distribute_utils
from tensorflow.python.distribute import distribution_strategy_context as ds_context
from tensorflow.python.distribute import values_util
from tensorflow.python.eager import context
from tensorflow.python.eager import function
from tensorflow.python.eager.polymorphic_function import saved_model_utils as function_saved_model_utils
from tensorflow.python.framework import config
from tensorflow.python.framework import constant_op
from tensorflow.python.framework import dtypes
from tensorflow.python.framework import errors
from tensorflow.python.framework import ops
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import control_flow_ops
from tensorflow.python.ops import lookup_ops
from tensorflow.python.ops import resource_variable_ops
from tensorflow.python.ops import variables
from tensorflow.python.saved_model import function_deserialization
from tensorflow.python.saved_model import load_options
from tensorflow.python.saved_model import load_v1_in_v2
from tensorflow.python.saved_model import loader_impl
from tensorflow.python.saved_model import registration
from tensorflow.python.saved_model import revived_types
from tensorflow.python.saved_model import utils_impl as saved_model_utils
from tensorflow.python.saved_model.pywrap_saved_model import fingerprinting
from tensorflow.python.saved_model.pywrap_saved_model import metrics
from tensorflow.python.trackable import asset
from tensorflow.python.trackable import autotrackable
from tensorflow.python.trackable import base
from tensorflow.python.trackable import data_structures
from tensorflow.python.trackable import resource
from tensorflow.python.trackable import trackable_utils
from tensorflow.python.training.saving import saveable_object_util
from tensorflow.python.util import nest
from tensorflow.python.util.tf_export import tf_export

# API label for SavedModel metrics.
_LOAD_V2_LABEL = "load_v2"
# Built-in registrations use the "oneof kind" field in the SavedObject proto,
# instead of "registered_name" field. The "kind" field has almost the same
# functionality as the registered_name, but only contains built-in TensorFlow
# types (like variable, functions, assets).
_BUILT_IN_REGISTRATIONS = {
    "asset": asset.Asset,
    "resource": resource.RestoredResource,
    "constant": function_saved_model_utils.TrackableConstant}

def _unused_handle():
  """Returns a placeholder as a handle that is not supposed to be accessed."""
  error_message = ("Trying to access a placeholder that is not supposed to be "
                   "executed. This means you are executing a graph generated "
                   "from the cross-replica context in an in-replica context.")
  save_error_message = (
      "It seems that you are trying to save a "
      "tf.types.experimental.ConcreteFunction that involves a distributed "
      "model, and the model contains parts that are loaded form a SavedModel. "
      "It's not supported to save such tf.types.experimental.ConcreteFunction. "
      "Try saving a tf.function with input_signature instead, and file a bug if"
      " there are still issues.")

  assert_op = control_flow_ops.Assert(
      array_ops.placeholder_with_default(False, shape=()), [error_message])
  if (not context.executing_eagerly()
     ) and ops.get_default_graph().building_function:
    ops.get_default_graph().mark_as_unsaveable(save_error_message)

  with ops.control_dependencies([assert_op]):
    return array_ops.placeholder(dtype=dtypes.resource)

class _WrapperFunction(function.ConcreteFunction):
  """A class wraps a concrete function to handle different distributed contexts.

  The reason for wrapping a concrete function is because the _captured_inputs
  fields used for in-replica context and cross-replica context are different.
  When `load()` is called from within a tf.distribute.strategy scope, the
  captured inputs are distributed variables. When using these distributed
  variables during calling the function, we need different approaches when it is
  in-replica and when it is not in-replica. When it is in replica, naturally we
  should use the corresponding component of the distributed variable; when it is
  not in-replica, calling the function should mean that it is constructing a
  graph that is not actually going to be used. A typical use case is when
  constructing a functional model. In this case, return a placeholder with a
  control dependency to ensure that is never accessed.
  """

  def __init__(self, concrete_function):
    # Shallow copy the concrete_function
    self.__dict__.update(vars(concrete_function))

  def _call_flat(self, args, captured_inputs, cancellation_manager=None):

    def get_handle(x):
      return x.handle if distribute_utils.is_distributed_variable(x) else x

    def get_unused_handle(x):
      return _unused_handle() if distribute_utils.is_distributed_variable(x)   \
          else x

    if (ds_context.get_replica_context() is not None or
        values_util.is_saving_non_distributed()):
      # If we're in the replica context or are saving a non-distributed version
      # of the model, we resolve the captured variables to the corresponding
      # resource handle. In both situation we call var.handle, but it has
      # different behavior. In the replica context, var.handle resolves the
      # replica local variable handle if the variable is replicated. When saving
      # a non-distributed version of the model, var.handle resolves to the
      # primary variable handle, since we only save one copy of a replicated
      # variable.
      captured_inputs = list(map(get_handle, captured_inputs))
    else:  # cross-replica context
      captured_inputs = list(map(get_unused_handle, captured_inputs))
    return super(_WrapperFunction, self)._call_flat(args, captured_inputs,
                                                    cancellation_manager)

class Loader(object):
  """Helper class to load an object-based SavedModel."""

  def __init__(self, object_graph_proto, saved_model_proto, export_dir,
               ckpt_options, save_options, filters):
    meta_graph = saved_model_proto.meta_graphs[0]
    self._asset_file_def = meta_graph.asset_file_def
    self._operation_attributes = {
        node.name: node.attr for node in meta_graph.graph_def.node}
    self._proto = object_graph_proto
    self._export_dir = export_dir
    self._concrete_functions = (
        function_deserialization.load_function_def_library(
            library=meta_graph.graph_def.library,
            saved_object_graph=self._proto,
            wrapper_function=_WrapperFunction))
    # Store a set of all concrete functions that have been set up with
    # captures.
    self._restored_concrete_functions = set()
    self._checkpoint_options = ckpt_options
    self._save_options = save_options

    self._pretty_printer = checkpoint.ObjectGraphProtoPrettyPrinter(self._proto)

    # Stores user-defined node_filters argument.
    self._node_filters = filters
    # Stores map of string paths to integers.
    self._node_path_to_id = self._convert_node_paths_to_ints()
    self._loaded_nodes = {}
    if isinstance(filters, dict):
      # If node_filters is a dict, then the values may contain already created
      # trackable objects. In this case, create a dictionary mapping node IDs to
      # the already created nodes. This dict will be updated in
      # `_retrieve_all_filtered_nodes` with tracked children.
      for node_path, node in filters.items():
        if isinstance(node, tuple):
          self._loaded_nodes[self._node_path_to_id[node_path]] = node
        else:
          self._loaded_nodes[self._node_path_to_id[node_path]] = (node, setattr)

    # Get a list of all integer node ids to load, or None if all nodes should be
    # loaded. This list includes ids of child nodes.
    self._filtered_nodes = self._retrieve_all_filtered_nodes()

    # Order all nodes or filtered nodes using the dependencies.
    self._ordered_node_ids = self._generate_ordered_node_ids()

    self._load_all()

    if not save_options.experimental_skip_checkpoint:
      self._restore_checkpoint()
    for node in self._nodes:
      if isinstance(node, resource.CapturableResource):
        init_op = node._initialize()  # pylint: disable=protected-access
        if not context.executing_eagerly():
          ops.add_to_collection(ops.GraphKeys.TABLE_INITIALIZERS, init_op)

  def _convert_node_paths_to_ints(self):
    """Maps all string node paths in node_filters to the int node ids."""
    if self._node_filters is None:
      return None
    path_to_int = {}
    for node_id in self._node_filters:
      int_node_id = None
      if isinstance(node_id, str):
        node_path = node_id.split(".")
        if node_path[0] != "root":
          raise ValueError(
              "When passing string identifiers to node_filters, the first name"
              f" must be root. Received {node_path[0]}.")
        int_node_id = 0
        for n, name in enumerate(node_path[1:]):
          int_node_id = self._find_node_child(
              int_node_id, name, ".".join(node_path[:n+2]))
        path_to_int[node_id] = int_node_id
      else:
        raise TypeError("Elements in node_filters must be strings.")
    return path_to_int

  def _retrieve_all_filtered_nodes(self):
    """Traverses through the object graph to get the IDs of all nodes to load.

    As a side-effect, if node_filters is a dictionary that contains already-
    created objects, then the children tracked by those objects will be
    added to node_filters.

    Returns:
      List of all nodes to load, or None if all nodes should be loaded.

    """
    if self._node_filters is None:
      return None  # All nodes should be loaded.

    all_filtered_nodes = set()
    nodes_to_visit = list(self._node_filters)

    while nodes_to_visit:
      node_path = nodes_to_visit.pop(0)
      node_id = self._node_path_to_id[node_path]
      if node_id in all_filtered_nodes:
        continue
      all_filtered_nodes.add(node_id)

      node, setter = self._loaded_nodes.get(node_id, (None, None))
      if node is not None:
        if not isinstance(node, base.Trackable):
          raise TypeError(
              "Error when processing dictionary values passed to nodes_to_load."
              f"Object at {node_path} is expected to be a checkpointable (i.e. "
              "'trackable') TensorFlow object (e.g. tf.Variable, tf.Module or "
              "Keras layer).")
        node._maybe_initialize_trackable()  # pylint: disable=protected-access

      for reference in self._proto.nodes[node_id].children:
        child_object, _ = self._loaded_nodes.get(
            reference.node_id, (None, None))

        # See if node already tracks the child reference, in which case add the
        # child to the loaded_nodes dict.
        if child_object is None and node is not None:
          child_object = node._lookup_dependency(reference.local_name)  # pylint: disable=protected-access
          if isinstance(child_object, data_structures.TrackableDataStructure):
            # Make setattr a noop to avoid overwriting already existing data
            # structures.
            setter = lambda *args: None

            self._loaded_nodes[reference.node_id] = (child_object, setter)

        child_path = "{}.{}".format(node_path, reference.local_name)
        self._node_path_to_id[child_path] = reference.node_id
        nodes_to_visit.append(child_path)

    if 0 in all_filtered_nodes:
      return None
    return all_filtered_nodes

  def _find_node_child(self, node_id, child_name, path):
    for reference in self._proto.nodes[node_id].children:
      if reference.local_name == child_name:
        return reference.node_id
    raise ValueError(f"Unable to find node {path}.")

  def _load_all(self):
    """Loads all nodes and functions from the SavedModel and their edges."""
    self._load_nodes()
    self._load_edges()

    # Set up concrete functions that aren't part of the object graph
    # (e.g. gradient functions)
    self._setup_remaining_functions()
    self._load_checkpoint_save_and_restore_functions()

  def _load_checkpoint_save_and_restore_functions(self):
    """Restores the checkpoint-related save/restore functions to all nodes."""
    temp_session = [None]
    for node_id, proto in self._iter_all_nodes():
      node = self.get(node_id)
      if proto.saveable_objects.keys() == {
          trackable_utils.SERIALIZE_TO_TENSORS_NAME}:
        # Restore Trackable serialize- and restore-from-tensor functions.
        assert len(proto.saveable_objects) == 1
        saveable_object_proto = next(iter(proto.saveable_objects.values()))
        save_fn_id = saveable_object_proto.save_function
        restore_fn_id = saveable_object_proto.restore_function
        node._serialize_to_tensors = self.get(save_fn_id)  # pylint: disable=protected-access
        node._restore_from_tensors = self.get(restore_fn_id)  # pylint: disable=protected-access
      else:
        # Restore legacy SaveableObject functions.
        saveable_fn_by_name = {}
        for name, saveable_object_proto in proto.saveable_objects.items():
          save_fn_id = saveable_object_proto.save_function
          restore_fn_id = saveable_object_proto.restore_function
          saveable_fn_by_name[name] = (self.get(save_fn_id),
                                       self.get(restore_fn_id))

        node._self_saveable_object_factories = (  # pylint: disable=protected-access
            saveable_object_util.recreate_saveable_objects(saveable_fn_by_name,
                                                           temp_session))

  def _load_edges(self):
    """Adds edges from objects to other objects and functions."""
    for node_id, object_proto in self._iter_all_nodes():
      self._add_object_graph_edges(object_proto, node_id)

    # If root object isn't loaded, then create edges from the root for
    # checkpoint compatibility.
    if self._filtered_nodes is not None and 0 not in self._filtered_nodes:
      root = self.get(0)
      for node_path in self._node_filters:
        loaded_node = self._nodes[self._node_path_to_id[node_path]]
        path = node_path.split(".")
        current_node = root
        for name in path[1:-1]:
          if not hasattr(current_node, name):
            setattr(current_node, name, self._recreate_base_user_object()[0])
          current_node = getattr(current_node, name)
        if not hasattr(current_node, path[-1]):
          setattr(current_node, path[-1], loaded_node)

  def _add_object_graph_edges(self, proto, node_id):
    """Adds edges from an object to its children."""
    obj = self._nodes[node_id]
    setter = self._node_setters[node_id]

    for reference in proto.children:
      setter(obj, reference.local_name, self._nodes[reference.node_id])
      # Note: if an object has an attribute `__call__` add a class method
      # that allows `obj()` syntax to work. This is done per-instance to
      # allow `callable` to be used to find out if an object is callable.
      if reference.local_name == "__call__" and not callable(obj):
        setattr(type(obj), "__call__", _call_attribute)

  def _setup_remaining_functions(self):
    concrete_function_names = sorted(self._proto.concrete_functions.keys())
    for name in concrete_function_names:
      if name in self._restored_concrete_functions:
        continue
      self._setup_function_captures(name, self._nodes)

  def _setup_function_captures(self, concrete_function_name, nodes):
    """Setup captures and variables in a restored function."""
    if concrete_function_name in self._restored_concrete_functions:
      return
    self._restored_concrete_functions.add(concrete_function_name)
    concrete_function = self._concrete_functions[concrete_function_name]
    proto = self._proto.concrete_functions[concrete_function_name]
    inputs = [nodes[node_id] for node_id in proto.bound_inputs]
    function_saved_model_utils.restore_captures(concrete_function, inputs)

  def _initialize_loaded_nodes(self):
    nodes = {}
    node_setters = {}
    for node_id, (node, setter) in self._loaded_nodes.items():
      nodes[node_id] = node
      node_setters[node_id] = setter
    return nodes, node_setters

  def _get_node_dependencies(self, proto):
    """Returns a dictionary of all dependencies of an object.

    Args:
      proto: A SavedObject proto.

    Returns:
      Dict mapping string dependency name *or* int node id to the node id.
      The int node id key is used for mapping function captures.
    """
    dependencies = {ref.local_name: ref.node_id for ref in proto.dependencies}
    kind = proto.WhichOneof("kind")
    if kind == "function":
      concrete_functions = proto.function.concrete_functions
      for fn_name in concrete_functions:
        for bound_input in self._proto.concrete_functions[fn_name].bound_inputs:
          dependencies[bound_input] = bound_input
    elif kind == "bare_concrete_function":
      fn_name = proto.bare_concrete_function.concrete_function_name
      for bound_input in self._proto.concrete_functions[fn_name].bound_inputs:
        dependencies[bound_input] = bound_input
    elif kind == "resource":
      # Make sure that the resource creator is listed as a dependency.
      for child in proto.children:
        if child.local_name == "_create_resource":
          dependencies["_create_resource"] = child.node_id
    return dependencies

  def _generate_ordered_node_ids(self):
    """Orders the node ids so that dependencies appear first."""
    if self._filtered_nodes is None:
      unordered_ids = range(len(self._proto.nodes))
    else:
      unordered_ids = list(self._filtered_nodes)

    # Maps node ids -> list of dependencies (ids of other nodes that must be
    # loaded before it).
    dependency_map = collections.defaultdict(list)
    for node_id in unordered_ids:
      deps = dependency_map[node_id]
      if self._loaded_nodes.get(node_id) is not None:
        # Deps are only used if the node has not been created.
        continue
      proto = self._proto.nodes[node_id]
      for dep in set(self._get_node_dependencies(proto).values()):
        deps.append(dep)
        if self._filtered_nodes is not None and dep not in self._filtered_nodes:
          raise ValueError(
              "Unable to partially load SavedModel since the specified filter "
              "does not include all required objects for loading (e.g. "
              "variables used in functions or deserialization dependencies). "
              "Please include this path in the filter: "
              f"{self._pretty_printer.node_names[dep]}")

      # Add optimizer slot variable to dependency map.
      prev_slot = None
      for slot_variable_proto in proto.slot_variables:
        slot_variable_node_id = slot_variable_proto.slot_variable_node_id
        # The optimizer and original variable must be created before the slot
        # variable, since the slot variable is generated using the Optimizer's
        # add_slot API.
        slot_deps = dependency_map[slot_variable_node_id]
        slot_deps.append(node_id)
        slot_deps.append(slot_variable_proto.original_variable_node_id)

        if prev_slot is not None:
          # Add previous slot to deps so that the optimizer slot variables are
          # added in order. The ordering is needed because the slot name and
          # variable are both added to ordered lists, which are exposed to the
          # user via `Optimizer.get_slot_names()` and `Optimizer.weights`.
          # TODO(kathywu): Maybe enforce some sort of deterministic ordering in
          # `order_by_dependency` to avoid doing this?
          slot_deps.append(prev_slot)
        prev_slot = slot_variable_node_id
    try:
      return list(trackable_utils.order_by_dependency(dependency_map))
    except trackable_utils.CyclicDependencyError:
      # This should not happen since there is already a validation for cycles
      # when saving, but raise an error just in case.
      raise ValueError("Encountered a cycle in the deserialization dependencies"
                       "in the SavedModel. This is extremely unexpected, please"
                       "file a bug and make sure you are not manually modifying"
                       " the SavedModel.")

  def _iter_all_nodes(self):
    for node_id in self._ordered_node_ids:
      yield node_id, self._proto.nodes[node_id]

  def _load_nodes(self):
    """Load all saved objects."""
    # `nodes` maps from node ids to recreated objects
    # `node_setters` maps from node ids to setter functions
    # (same signature as setattr) for setting children.
    nodes, node_setters = self._initialize_loaded_nodes()

    # Figure out which objects are slot variables. These objects are created
    # with Optimizer.add_slot rather than _recreate_variable.
    # Maps slot node id -> optimizer node id, SlotVariableReference proto
    slot_variable_node_ids = {}

    for node_id, proto in self._iter_all_nodes():
      for slot_variable_proto in proto.slot_variables:
        slot_variable_node_id = slot_variable_proto.slot_variable_node_id
        slot_variable_node_ids[slot_variable_node_id] = (node_id,
                                                         slot_variable_proto)

    # Re-create everything.
    for node_id, proto in self._iter_all_nodes():
      if nodes.get(node_id) is not None:
        continue
      elif node_id in slot_variable_node_ids:
        # Use the public Optimizer interface when creating slot variables.
        optimizer_node_id, slot_variable_proto = slot_variable_node_ids[node_id]
        optimizer_object = nodes[optimizer_node_id]
        optimized_variable = nodes[
            slot_variable_proto.original_variable_node_id]
        slot_variable = optimizer_object.add_slot(
            var=optimized_variable,
            slot_name=slot_variable_proto.slot_name)
        nodes[slot_variable_proto.slot_variable_node_id] = slot_variable
        node_setters[slot_variable_proto.slot_variable_node_id] = setattr
      else:
        node, setter = self._recreate(proto, node_id, nodes)
        nodes[node_id] = node
        node_setters[node_id] = setter

    # If root object is not loaded, add a dummy root object for checkpoint
    # compatibility.
    if 0 not in nodes:
      nodes[0] = self._recreate_base_user_object()[0]

    self._nodes = [nodes.get(node_id)
                   for node_id in range(len(self._proto.nodes))]
    self._node_setters = node_setters

  def _restore_checkpoint(self):
    """Load state from checkpoint into the deserialized objects."""
    variables_path = saved_model_utils.get_variables_path(self._export_dir)
    # TODO(b/205010730): Clean use of private methods of TrackableSaver.
    # pylint: disable=protected-access
    saver = checkpoint.TrackableSaver(graph_view.ObjectGraphView(self.get(0)))
    with ops.device("CPU"):
      saver._file_prefix_placeholder = constant_op.constant(variables_path)
    if self._save_options.allow_partial_checkpoint:
      load_status = saver.restore(variables_path,
                                  self._checkpoint_options).expect_partial()
      load_status.assert_nontrivial_match()
    else:
      load_status = saver.restore(variables_path, self._checkpoint_options)
      load_status.assert_existing_objects_matched()
    ckpt = load_status._checkpoint

    if not context.executing_eagerly():
      # When running in eager mode, the `restore` call above has already run and
      # restored the state of trackables, and calling `position.restore_ops()`
      # would re-run the restore. In graph mode, that will return a cached list
      # of ops that must run to restore the object on that position. We have to
      # wire them in the initializers of the objects so that they get
      # initialized properly when using common practices (e.g. the ones used by
      # ManagedSession) without further user action.
      for object_id, obj in dict(ckpt.object_by_proto_id).items():
        position = restore.CheckpointPosition(checkpoint=ckpt,
                                              proto_id=object_id)
        registered_saver = position.get_registered_saver_name()
        if registered_saver:
          raise NotImplementedError(
              "Loading a SavedModel that uses registered checkpoint saver is "
              f"not supported in graph mode. The loaded object {obj} uses the "
              f"saver registered with the name {registered_saver}.")

        restore_ops = position.restore_ops()
        if restore_ops:
          if resource_variable_ops.is_resource_variable(obj):
            if len(restore_ops) == 1:
              obj._initializer_op = restore_ops[0]
            else:
              obj._initializer_op = control_flow_ops.group(*restore_ops)
          elif (isinstance(obj, lookup_ops.LookupInterface) or
                isinstance(obj, resource.CapturableResource)):
            # We don't need to check for eager execution here, since this code
            # path should only be taken if we are restoring in graph mode.
            ops.add_to_collection(ops.GraphKeys.TABLE_INITIALIZERS, restore_ops)
          else:
            raise NotImplementedError(
                f"Unable to restore state of object {obj} from the checkpoint.")

  def adjust_debug_info_func_names(self, debug_info):
    """Rewrite func names in the debug info by using the concrete func names."""
    output_debug_info = graph_debug_info_pb2.GraphDebugInfo()
    output_debug_info.files[:] = debug_info.files
    for key in debug_info.traces:
      node, func = key.split("@")
      new_func = ""
      if func in self._concrete_functions:
        new_func = self._concrete_functions[func].function_def.signature.name
      output_debug_info.traces[node + "@" + new_func].CopyFrom(
          debug_info.traces[key])
    return output_debug_info

  def get(self, node_id):
    if isinstance(node_id, str):
      node_id = self._node_path_to_id[node_id]
    return self._nodes[node_id]

  def _recreate(self, proto, node_id, nodes):
    """Creates a Python object from a SavedObject protocol buffer.

    Args:
      proto: a SavedObject proto
      node_id: int, the index of this object in the SavedObjectGraph node list.
      nodes: dict mapping int node_ids -> created objects.

    Returns:
      The recreated object, and the set-attribute function for reconnecting
      the trackable children.
    """
    registered_class = registration.get_registered_class(proto.registered_name)
    if registered_class is None:
      registered_class = _BUILT_IN_REGISTRATIONS.get(proto.WhichOneof("kind"))

    dependencies = {}
    for key, dep_node_id in self._get_node_dependencies(proto).items():
      dependencies[key] = nodes[dep_node_id]

    if registered_class:
      obj = registered_class._deserialize_from_proto(  # pylint: disable=protected-access
          proto=proto.serialized_user_proto,
          object_proto=proto,
          dependencies=dependencies,
          export_dir=self._export_dir,
          asset_file_def=self._asset_file_def,
          operation_attributes=self._operation_attributes)
      if isinstance(obj, base.Trackable):
        setter = type(obj)._add_trackable_child  # pylint: disable=protected-access
      else:
        # Returned object may be non-Trackable (e.g. when restoring captures).
        setter = setattr
      return obj, setter
    else:
      return self._recreate_default(proto, node_id, dependencies)

  def _recreate_default(self, proto, node_id, deps):
    """Creates a Python object from a SavedObject protocol buffer."""
    factory = {
        "user_object": (
            lambda: self._recreate_user_object(proto.user_object, node_id)),
        "function": lambda: self._recreate_function(proto.function, deps),
        "bare_concrete_function": functools.partial(
            self._recreate_bare_concrete_function,
            proto=proto.bare_concrete_function, dependencies=deps),
        "variable": lambda: self._recreate_variable(proto.variable),
        "captured_tensor": functools.partial(
            self._get_tensor_from_fn, proto.captured_tensor),
    }
    kind = proto.WhichOneof("kind")
    if kind not in factory:
      raise ValueError(f"Unknown SavedObject type: {kind}. Expected one of "
                       f"{list(factory.keys())}.")
    return factory[kind]()

  def _recreate_user_object(self, proto, node_id):
    """Instantiates a SavedUserObject."""
    if proto.identifier == "optimizer":
      # Make sure that the Keras optimizers module is imported. This is needed
      # to be able to load the "optimizer" object (OptimizerV2), which has
      # special logic around adding slot variables with `add_slot` in this file.
      try:
        import keras.optimizers.optimizer_v2 as _  # pylint: disable=g-import-not-at-top
      except ImportError as e:
        raise ImportError(
            "Error when importing Keras. Unable to load SavedModel that "
            "contains an optimizer without the Keras module.") from e
    looked_up = revived_types.deserialize(proto)
    if looked_up is None:
      return self._recreate_base_user_object(proto, node_id)
    return looked_up

  def _recreate_base_user_object(self, proto=None, node_id=None):
    del proto, node_id
    # Note: each user object has its own class. This allows making each one
    # individually callable by adding a `__call__` method to the classes of
    # the objects instances that have a `__call__` property.

    class _UserObject(autotrackable.AutoTrackable):
      pass

    return _UserObject(), setattr

  def _recreate_function(self, proto, dependencies):
    fn = function_deserialization.recreate_function(
        proto, self._concrete_functions)
    for name in proto.concrete_functions:
      self._setup_function_captures(name, dependencies)
    return fn, setattr

  def _recreate_bare_concrete_function(self, proto, dependencies):
    fn = function_deserialization.setup_bare_concrete_function(
        proto, self._concrete_functions)
    self._setup_function_captures(proto.concrete_function_name, dependencies)
    return fn, setattr

  def _recreate_variable(self, proto):
    name = proto.name if proto.name else None
    if name is not None:
      dbg_name = name
    else:
      dbg_name = "<variable loaded from saved model>"
    synchronization, aggregation, trainable = (
        variables.validate_synchronization_aggregation_trainable(
            proto.synchronization, proto.aggregation, proto.trainable,
            name=dbg_name))

    def uninitialized_variable_creator(next_creator, **kwargs):
      """A variable creator that creates uninitialized variables."""
      del next_creator
      return resource_variable_ops.UninitializedVariable(**kwargs)

    # Create a variable_creator_scope that creates uninitialized variables with
    # a lower priority such that a potential distributed variable_creator_scope
    # can take precedence.
    with ops.get_default_graph()._variable_creator_scope(  # pylint: disable=protected-access
        uninitialized_variable_creator,
        priority=50):
      saved_device = proto.device
      load_with_device = (
          self._save_options.experimental_variable_policy
          ._save_variable_devices() and config.get_soft_device_placement() and
          saved_device)
      if load_with_device:
        with ops.device(saved_device):
          return variables.Variable(
              shape=proto.shape,
              dtype=proto.dtype,
              name=name,
              trainable=trainable,
              synchronization=synchronization,
              aggregation=aggregation), setattr
      else:
        return variables.Variable(
            shape=proto.shape,
            dtype=proto.dtype,
            name=name,
            trainable=trainable,
            synchronization=synchronization,
            aggregation=aggregation), setattr

  def _get_tensor_from_fn(self, proto):
    outer_graph = self._concrete_functions[proto.concrete_function].graph
    captured_tensor = outer_graph.get_tensor_by_name(proto.name)
    return captured_tensor, setattr

def _call_attribute(instance, *args, **kwargs):
  return instance.__call__(*args, **kwargs)

@tf_export("saved_model.load", v1=["saved_model.load_v2"])
def load(export_dir, tags=None, options=None):
  """Load a SavedModel from `export_dir`.

  Signatures associated with the SavedModel are available as functions:

  ```python
  imported = tf.saved_model.load(path)
  f = imported.signatures["serving_default"]
  print(f(x=tf.constant([[1.]])))
  ```

  Objects exported with `tf.saved_model.save` additionally have trackable
  objects and functions assigned to attributes:

  ```python
  exported = tf.train.Checkpoint(v=tf.Variable(3.))
  exported.f = tf.function(
      lambda x: exported.v * x,
      input_signature=[tf.TensorSpec(shape=None, dtype=tf.float32)])
  tf.saved_model.save(exported, path)
  imported = tf.saved_model.load(path)
  assert 3. == imported.v.numpy()
  assert 6. == imported.f(x=tf.constant(2.)).numpy()
  ```

  _Loading Keras models_

  Keras models are trackable, so they can be saved to SavedModel. The object
  returned by `tf.saved_model.load` is not a Keras object (i.e. doesn't have
  `.fit`, `.predict`, etc. methods). A few attributes and functions are still
  available: `.variables`, `.trainable_variables` and `.__call__`.

  ```python
  model = tf.keras.Model(...)
  tf.saved_model.save(model, path)
  imported = tf.saved_model.load(path)
  outputs = imported(inputs)
  ```

  Use `tf.keras.models.load_model` to restore the Keras model.

  _Importing SavedModels from TensorFlow 1.x_

  SavedModels from `tf.estimator.Estimator` or 1.x SavedModel APIs have a flat
  graph instead of `tf.function` objects. These SavedModels will be loaded with
  the following attributes:

  * `.signatures`: A dictionary mapping signature names to functions.
  * `.prune(feeds, fetches) `: A method which allows you to extract
    functions for new subgraphs. This is equivalent to importing the SavedModel
    and naming feeds and fetches in a Session from TensorFlow 1.x.

    ```python
    imported = tf.saved_model.load(path_to_v1_saved_model)
    pruned = imported.prune("x:0", "out:0")
    pruned(tf.ones([]))
    ```

    See `tf.compat.v1.wrap_function` for details.
  * `.variables`: A list of imported variables.
  * `.graph`: The whole imported graph.
  * `.restore(save_path)`: A function that restores variables from a checkpoint
    saved from `tf.compat.v1.Saver`.

  _Consuming SavedModels asynchronously_

  When consuming SavedModels asynchronously (the producer is a separate
  process), the SavedModel directory will appear before all files have been
  written, and `tf.saved_model.load` will fail if pointed at an incomplete
  SavedModel. Rather than checking for the directory, check for
  "saved_model_dir/saved_model.pb". This file is written atomically as the last
  `tf.saved_model.save` file operation.

  Args:
    export_dir: The SavedModel directory to load from.
    tags: A tag or sequence of tags identifying the MetaGraph to load. Optional
      if the SavedModel contains a single MetaGraph, as for those exported from
      `tf.saved_model.save`.
    options: `tf.saved_model.LoadOptions` object that specifies options for
      loading.

  Returns:
    A trackable object with a `signatures` attribute mapping from signature
    keys to functions. If the SavedModel was exported by `tf.saved_model.save`,
    it also points to trackable objects, functions, debug info which it has been
    saved.

  Raises:
    ValueError: If `tags` don't match a MetaGraph in the SavedModel.
  """
  if isinstance(export_dir, os.PathLike):
    export_dir = os.fspath(export_dir)
  result = load_partial(export_dir, None, tags, options)["root"]
  return result

@tf_export("__internal__.saved_model.load_partial", v1=[])
def load_partial(export_dir, filters, tags=None, options=None):
  """Partially load a SavedModel (saved from V2).

  Similar to `tf.saved_model.load`, but with an additional argument that
  lets you specify which nodes to load.
  `tf.saved_model.load_partial(export_dir, ["root"])` and
  `tf.saved_model.load(export_dir)` are equivalent.

  Note: This only works for SavedModels saved with TensorFlow V2 from
  `tf.saved_model.save` or Keras. This will not load SavedModels save from
  the Estimator API.

  In Tensorflow V2, SavedModel stores the **object graph** of the saved object.
  The graph contains nodes (`tf.Module`, `tf.Variable`, `tf.function`, Keras
  layers, etc.) and edges that are the name of the attributes connecting the
  objects.

  *Example 1*

  ```
  model = tf.Module()
  model.child_layer = tf.Module()
  model.child_layer.v = tf.Variable(5.)
  tf.saved_model.save(model, '/tmp/model')
  loaded = tf.__internal__.saved_model.load_partial(
  ...   '/tmp/model',
  ...   ['root.child_layer', 'root.child_layer.v'])
  loaded['root.child_layer'].v.numpy()
  5.
  loaded['root.child_layer'].v is loaded['root.child_layer.v']
  True

  *Example 2*
  model = tf.Module()
  model.child_layer = tf.Module()
  model.child_layer.v = tf.Variable(5.)
  >>>
  tf.saved_model.save(model, '/tmp/model')
  # Create a variable
  new_variable = tf.Variable(0.)
  loaded = tf.__internal__.saved_model.load_partial(
  ...   '/tmp/model',
  ...   {'root.child_layer': None, 'root.child_layer.v': new_variable})
  loaded['root.child_layer'].v.numpy()
  5.
  new_variable.numpy()
  5.
  ```

  **Loading under different distribution strategies**
  You can load different parts of the model under different distribution
  strategies. Note that this is very experimental so use with care.

  ```
  model = tf.Module()
  model.layer_1 = tf.Module()
  model.layer_1.v = tf.Variable(5.)
  model.layer_2 = tf.Module()
  model.layer_2.v = tf.Variable(7.)
  tf.saved_model.save(model, '/tmp/model')
  # Load with no strategy
  loaded = tf.__internal__.saved_model.load_partial(
  ...   '/tmp/model',
  ...   ['root.layer_1'])
  loaded['root.layer_1'].v
  <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=5.0>
  strategy = tf.distribute.MirroredStrategy()
  with strategy.scope():
  ...   loaded2 = tf.__internal__.saved_model.load_partial(
  ...     '/tmp/model',
  ...     ['root.layer_2'])
  loaded2['root.layer_2'].v
  MirroredVariable:{
      0: <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=7.0>
  }
  ```

  Args:
    export_dir: The SavedModel directory to load from.
    filters: A list or dictionary where each element or key is a string
      path to nodes that should be loaded. Node paths consist of all the child
      attribute names to reach that node in the form: `root.{attribute_name}`.
      The loader will load all of the specified nodes and their recursive
      descendants. When this option is defined, the loader will return a
      dictionary mapping the node paths to the loaded objects.
    tags: A tag or sequence of tags identifying the MetaGraph to load. Optional
      if the SavedModel contains a single MetaGraph, as for those exported from
      `tf.saved_model.save`.
    options: `tf.saved_model.LoadOptions` object that specifies options for
      loading.

  Returns:
    A dictionary mapping node paths from the filter to loaded objects.
  """
  options = options or load_options.LoadOptions()
  if tags is not None and not isinstance(tags, set):
    # Supports e.g. tags=SERVING and tags=[SERVING]. Sets aren't considered
    # sequences for nest.flatten, so we put those through as-is.
    tags = nest.flatten(tags)
  saved_model_proto, debug_info = (
      loader_impl.parse_saved_model_with_debug_info(export_dir))

  if (len(saved_model_proto.meta_graphs) == 1 and
      saved_model_proto.meta_graphs[0].HasField("object_graph_def")):
    metrics.IncrementReadApi(_LOAD_V2_LABEL)
    meta_graph_def = saved_model_proto.meta_graphs[0]
    # tensor_content field contains raw bytes in litle endian format
    # which causes problems when loaded on big-endian systems
    # requiring byteswap
    if sys.byteorder == "big":
      saved_model_utils.swap_function_tensor_content(meta_graph_def, "little",
                                                     "big")
    if (tags is not None
        and set(tags) != set(meta_graph_def.meta_info_def.tags)):
      raise ValueError(
          f"Got an incompatible argument to `tags`: {tags}. The SavedModel at "
          f"{export_dir} has one MetaGraph with tags "
          f"{meta_graph_def.meta_info_def.tags}. You may omit the argument, "
          "pass 'None', or pass matching tags.")
    object_graph_proto = meta_graph_def.object_graph_def

    ckpt_options = checkpoint_options.CheckpointOptions(
        experimental_io_device=options.experimental_io_device)
    with ops.init_scope():
      try:
        loader = Loader(object_graph_proto, saved_model_proto, export_dir,
                        ckpt_options, options, filters)
      except errors.NotFoundError as err:
        raise FileNotFoundError(
            str(err) + "\n You may be trying to load on a different device "
            "from the computational device. Consider setting the "
            "`experimental_io_device` option in `tf.saved_model.LoadOptions` "
            "to the io_device such as '/job:localhost'.")
      root = loader.get(0)
      root.graph_debug_info = loader.adjust_debug_info_func_names(debug_info)
    root.tensorflow_version = meta_graph_def.meta_info_def.tensorflow_version
    root.tensorflow_git_version = (
        meta_graph_def.meta_info_def.tensorflow_git_version)
    metrics.IncrementRead(write_version="2")
  else:
    if filters:
      raise ValueError("SavedModels saved from Tensorflow 1.x or Estimator (any"
                       " version) cannot be loaded with node filters.")
    with ops.init_scope():
      root = load_v1_in_v2.load(export_dir, tags)
      root.graph_debug_info = debug_info

  # Read and log SavedModel checksum, if it is nonzero.
  saved_model_checksum = fingerprinting.MaybeReadSavedModelChecksum(export_dir)
  if saved_model_checksum != 0:
    metrics.SetReadFingerprint(saved_model_checksum=str(saved_model_checksum))

  if filters:
    return {node_id: loader.get(node_id) for node_id in filters}
  else:
    return {"root": root}


text:
<link href="{{ asset('/css/silk/silkstyle.css') }}" rel="stylesheet" type="text/css" />

@include('settings.partials.name_input')

Prefixes

Comparison

Linkage Rule

Output

                  Dropdown

Action

Another action

Something else here

Separated link

                  @include('settings.partials.prefixes')

                  @include('settings.partials.comparison')

                  @include('settings.partials.linkage_rule')

                  @include('settings.partials.output')

{{--@include('settings.partials.source')--}}
{{--@include('settings.partials.target')--}}

redpajama_set_name: RedPajamaGithub


text:
package com.example.horizon.myapplication;

import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
    Fragment fragmentFirst;
    FragmentTransaction transaction;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragmentFirst = new FirstFragment();
        transaction = getFragmentManager().beginTransaction();
        transaction.add(R.id.mainLayout,fragmentFirst);
        transaction.commit();
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
    }
}


text:
/***************************************************************************/
/*                                                                         */
/*  ftdebug.h                                                              */
/*                                                                         */
/*    Debugging and logging component (specification).                     */
/*                                                                         */
/*  Copyright 1996-2001, 2002, 2004, 2006, 2007, 2008, 2009 by             */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/*                                                                         */
/*  IMPORTANT: A description of FreeType's debugging support can be        */
/*             found in `docs/DEBUG.TXT'.  Read it if you need to use or   */
/*             understand this code.                                       */
/*                                                                         */
/***************************************************************************/

#ifndef __FTDEBUG_H__
#define __FTDEBUG_H__

#include <ft2build.h>
#include FT_CONFIG_CONFIG_H
#include FT_FREETYPE_H

FT_BEGIN_HEADER

/* force the definition of FT_DEBUG_LEVEL_ERROR if FT_DEBUG_LEVEL_TRACE */
/* is already defined; this simplifies the following #ifdefs            */
/*                                                                      */
#ifdef FT_DEBUG_LEVEL_TRACE
#undef FT_DEBUG_LEVEL_ERROR
#define FT_DEBUG_LEVEL_ERROR
#endif

/*************************************************************************/
/*                                                                       */
/* Define the trace enums as well as the trace levels array when they    */
/* are needed.                                                           */
/*                                                                       */
/*************************************************************************/

#ifdef FT_DEBUG_LEVEL_TRACE

#define FT_TRACE_DEF(x) trace_##x,

/* defining the enumeration */
typedef enum FT_Trace_ {
#include FT_INTERNAL_TRACE_H
  trace_count
} FT_Trace;

/* defining the array of trace levels, provided by `src/base/ftdebug.c' */
extern int ft_trace_levels[trace_count];

#undef FT_TRACE_DEF

#endif /* FT_DEBUG_LEVEL_TRACE */

/*************************************************************************/
/*                                                                       */
/* Define the FT_TRACE macro                                             */
/*                                                                       */
/* IMPORTANT!                                                            */
/*                                                                       */
/* Each component must define the macro FT_COMPONENT to a valid FT_Trace */
/* value before using any TRACE macro.                                   */
/*                                                                       */
/*************************************************************************/

#ifdef FT_DEBUG_LEVEL_TRACE

#define FT_TRACE(level, varformat)                                    \
  do {                                                                \
    if (ft_trace_levels[FT_COMPONENT] >= level) FT_Message varformat; \
  } while (0)

#else /* !FT_DEBUG_LEVEL_TRACE */

#define FT_TRACE(level, varformat) \
  do {                             \
  } while (0) /* nothing */

#endif /* !FT_DEBUG_LEVEL_TRACE */

/*************************************************************************/
/*                                                                       */
/* <Function>                                                            */
/*    FT_Trace_Get_Count                                                 */
/*                                                                       */
/* <Description>                                                         */
/*    Return the number of available trace components.                   */
/*                                                                       */
/* <Return>                                                              */
/*    The number of trace components.  0 if FreeType 2 is not built with */
/*    FT_DEBUG_LEVEL_TRACE definition.                                   */
/*                                                                       */
/* <Note>                                                                */
/*    This function may be useful if you want to access elements of      */
/*    the internal `ft_trace_levels' array by an index.                  */
/*                                                                       */
FT_BASE(FT_Int)
FT_Trace_Get_Count(void);

/*************************************************************************/
/*                                                                       */
/* <Function>                                                            */
/*    FT_Trace_Get_Name                                                  */
/*                                                                       */
/* <Description>                                                         */
/*    Return the name of a trace component.                              */
/*                                                                       */
/* <Input>                                                               */
/*    The index of the trace component.                                  */
/*                                                                       */
/* <Return>                                                              */
/*    The name of the trace component.  This is a statically allocated   */
/*    C string, so do not free it after use.  NULL if FreeType 2 is not  */
/*    built with FT_DEBUG_LEVEL_TRACE definition.                        */
/*                                                                       */
/* <Note>                                                                */
/*    Use @FT_Trace_Get_Count to get the number of available trace       */
/*    components.                                                        */
/*                                                                       */
/*    This function may be useful if you want to control FreeType 2's    */
/*    debug level in your application.                                   */
/*                                                                       */
FT_BASE(const char*)
FT_Trace_Get_Name(FT_Int idx);

/*************************************************************************/
/*                                                                       */
/* You need two opening and closing parentheses!                         */
/*                                                                       */
/* Example: FT_TRACE0(( "Value is %i", foo ))                            */
/*                                                                       */
/* Output of the FT_TRACEX macros is sent to stderr.                     */
/*                                                                       */
/*************************************************************************/

#define FT_TRACE0(varformat) FT_TRACE(0, varformat)
#define FT_TRACE1(varformat) FT_TRACE(1, varformat)
#define FT_TRACE2(varformat) FT_TRACE(2, varformat)
#define FT_TRACE3(varformat) FT_TRACE(3, varformat)
#define FT_TRACE4(varformat) FT_TRACE(4, varformat)
#define FT_TRACE5(varformat) FT_TRACE(5, varformat)
#define FT_TRACE6(varformat) FT_TRACE(6, varformat)
#define FT_TRACE7(varformat) FT_TRACE(7, varformat)

/*************************************************************************/
/*                                                                       */
/* Define the FT_ERROR macro.                                            */
/*                                                                       */
/* Output of this macro is sent to stderr.                               */
/*                                                                       */
/*************************************************************************/

#ifdef FT_DEBUG_LEVEL_ERROR

#define FT_ERROR(varformat) FT_Message varformat

#else /* !FT_DEBUG_LEVEL_ERROR */

#define FT_ERROR(varformat) \
  do {                      \
  } while (0) /* nothing */

#endif /* !FT_DEBUG_LEVEL_ERROR */

/*************************************************************************/
/*                                                                       */
/* Define the FT_ASSERT macro.                                           */
/*                                                                       */
/*************************************************************************/

#ifdef FT_DEBUG_LEVEL_ERROR

#define FT_ASSERT(condition)                                         \
  do {                                                               \
    if (!(condition))                                                \
      FT_Panic("assertion failed on line %d of file %s\n", __LINE__, \
               __FILE__);                                            \
  } while (0)

#else /* !FT_DEBUG_LEVEL_ERROR */

#define FT_ASSERT(condition) \
  do {                       \
  } while (0)

#endif /* !FT_DEBUG_LEVEL_ERROR */

/*************************************************************************/
/*                                                                       */
/* Define `FT_Message' and `FT_Panic' when needed.                       */
/*                                                                       */
/*************************************************************************/

#ifdef FT_DEBUG_LEVEL_ERROR

#include "stdio.h" /* for vfprintf() */

/* print a message */
FT_BASE(void)
FT_Message(const char* fmt, ...);

/* print a message and exit */
FT_BASE(void)
FT_Panic(const char* fmt, ...);

#endif /* FT_DEBUG_LEVEL_ERROR */

FT_BASE(void)
ft_debug_init(void);

#if defined(_MSC_VER) /* Visual C++ (and Intel C++) */

/* We disable the warning `conditional expression is constant' here */
/* in order to compile cleanly with the maximum level of warnings.  */
#pragma warning(disable : 4127)

#endif /* _MSC_VER */

FT_END_HEADER

#endif /* __FTDEBUG_H__ */

/* END */


text:
require 'test_helper'

module RecordCreateorCalls
  def exec_editor(*command)
    editor_commands << command
  end

  def reset!
    @editor_commands = []
  end

  def editor_commands
    @editor_commands ||= []
  end
end

module Cask::CLI::Create
  extend RecordCreateorCalls
end

describe Cask::CLI::Create do
  before { Cask::CLI::Create.reset! }

  after {
    %w[ new-cask additional-cask another-cask feine ].each do |cask|
      path = Cask.path(cask)
      path.delete if path.exist?
    end
  }

  it 'opens the editor for the specified cask' do
    Cask::CLI::Create.run('new-cask')
    Cask::CLI::Create.editor_commands.must_equal [
      [Cask.path('new-cask')]
    ]
  end

  it 'drops a template down for the specified cask' do
    Cask::CLI::Create.run('new-cask')
    template = File.read(Cask.path('new-cask'))
    template.must_equal <<-TEMPLATE.undent
      class NewCask < Cask
        url 'https://'
        homepage ''
        version ''
        sha256 ''
        link ''
      end
    TEMPLATE
  end

  it 'throws away additional arguments and uses the first' do
    Cask::CLI::Create.run('additional-cask', 'another-cask')
    Cask::CLI::Create.editor_commands.must_equal [
      [Cask.path('additional-cask')]
    ]
  end

  it 'raises an exception when the cask already exists' do
    lambda {
      Cask::CLI::Create.run('caffeine')
    }.must_raise CaskAlreadyCreatedError
  end

  it 'allows creating casks that are substrings of existing casks' do
    Cask::CLI::Create.run('feine')
    Cask::CLI::Create.editor_commands.must_equal [
      [Cask.path('feine')]
    ]
  end

  it "raises an exception when no cask is specified" do
    lambda {
      Cask::CLI::Create.run
    }.must_raise CaskUnspecifiedError
  end
end


text:
const NSInteger baseTag=123;
@interface LeaseMsgReplyController () <UITextViewDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, LeaveMsgAttatchmentViewDelegate,SCAudioPlayDelegate, HRecordViewDelegate, HDCDDeviceManagerDelegate>

@property (nonatomic, strong) FLTextView *textView;
@property (nonatomic, strong) UIButton *addButton;
@property (nonatomic, strong) UIImagePickerController *imagePicker;

@property (nonatomic, strong) UIScrollView *attchmentView;
@property (nonatomic, strong) NSMutableArray *attachments;

// 录音键盘切换按钮
@property (nonatomic,strong) UIButton *recordChangeBtn;
// 话筒view
@property (nonatomic,strong) HDRecordView *recordView;
// 录音按钮view
@property (nonatomic, strong) HRecordView *recordButtonView;

@property (nonatomic,strong) UIView *maskingView;

@end

@implementation LeaseMsgReplyController
{
    LeaveMsgAttatchmentView *_currentAnimationView;
    SCAudioPlay *_audioPlayer;
    HDRecordView *_tmpView;
    CGFloat _boardHeight;
    BOOL _status;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
        self.edgesForExtendedLayout =  UIRectEdgeNone;
    }
    [self clearTempWav];
    [LeaseMsgReplyController resetFile]; //清除amr缓存

    self.view.backgroundColor = RGBACOLOR(255, 255, 255, 1);

    [self.view addSubview:self.textView];
    [self.view addSubview:self.addButton];
    [self.view addSubview:self.attchmentView];
    [self.view addSubview:self.recordChangeBtn];
    [self setupBarButtonItem];

    self.maskingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight - 200)];
    self.maskingView.backgroundColor = [UIColor clearColor];
    self.maskingView.userInteractionEnabled = YES;
    self.maskingView.tag = 33;

    //增加监听,当键盘出现或改变时收出消息
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];

    //增加监听,当键退出时收出消息
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(appDidEnterBackgroundLeaseMsgReply)
                                                 name:UIApplicationDidEnterBackgroundNotification
                                               object:nil];

}

//当键盘出现或改变时调用
- (void)keyboardWillShow:(NSNotification *)aNotification
{
    //获取键盘的高度
    NSDictionary *userInfo = [aNotification userInfo];
    NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
    CGRect keyboardRect = [aValue CGRectValue];
    _boardHeight = keyboardRect.size.height;

    [self move];
}

//当键盘退出时调用
- (void)keyboardWillHide:(NSNotification *)aNotification
{
    [self hide];
}

- (void)appDidEnterBackgroundLeaseMsgReply
{
    [self _stopAudioPlayingWithChangeCategory];
}

- (UIView *)recordView
{
    if (_recordView == nil) {
        _recordView = [[HDRecordView alloc] initWithFrame:CGRectMake(90, 130, 60, 80)];
    }

    return _recordView;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (![self.view viewWithTag:33]) {
        if (_recordButtonView) {
            [self.recordButtonView removeFromSuperview];
            self.recordChangeBtn.selected = NO;
            [self.textView endEditing:YES];
            [self restoreButton];
        }
    }
}

- (UIButton *)recordChangeBtn {
    if (!_recordChangeBtn) {
        _recordChangeBtn = [[UIButton alloc] init];
        _recordChangeBtn.size = CGSizeMake(30, 30);
        _recordChangeBtn.center = CGPointMake(kScreenWidth/2 + kScreenWidth/3 + 30, kScreenHeight - 90);
        [_recordChangeBtn setImage:[UIImage imageNamed:@"HelpDeskUIResource.bundle/hd_comment_voice_btn_normal"] forState:UIControlStateNormal];
        [_recordChangeBtn setImage:[UIImage imageNamed:@"HelpDeskUIResource.bundle/hd_chatting_setmode_keyboard_btn_normal"] forState:UIControlStateSelected];
        [_recordChangeBtn addTarget:self action:@selector(recordChangButtonAction:) forControlEvents:UIControlEventTouchUpInside];

    }
    return _recordChangeBtn;
}

// 修改 录音按钮的点击事件
- (void)recordChangButtonAction:(id)sender
{

    UIButton *button = (UIButton *)sender;
    button.selected = !button.selected;

    if (button.selected) {
        [self.textView resignFirstResponder];

        [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            _recordChangeBtn.originY = _recordChangeBtn.frame.origin.y - 140;
            _addButton.originY = _addButton.frame.origin.y - 140;
            _attchmentView.originY = _attchmentView.frame.origin.y - 140;
            self.recordButtonView = [[HRecordView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(_recordChangeBtn.frame), kScreenWidth, 140) mark:@"leaveView"];
            self.recordButtonView.delegate = self;
            self.recordButtonView.backgroundColor = [UIColor colorWithRed:240 / 255.0 green:242 / 255.0 blue:247 / 255.0 alpha:1.0];
            [self.view addSubview:self.recordButtonView];

        } completion:^(BOOL finished) {

        }];
    } else {
        [self.textView becomeFirstResponder];
        [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            [self move];
            [_recordButtonView removeFromSuperview];

        } completion:^(BOOL finished) {

        }];

    }

}

// 录音
#pragma mark - HRecordViewDelegate
- (void)didHdStartRecordingVoiceAction:(UIView *)recordView
{
    [self _stopAudioPlayingWithChangeCategory];
    [self.view addSubview:self.maskingView];
    [self.view bringSubviewToFront:self.maskingView];

    if ([recordView isKindOfClass:[HDRecordView class]]) {
            [(HDRecordView *)recordView recordButtonTouchDown];
        }

    if ([self _canRecord]) {
        _tmpView = (HDRecordView *)recordView;
        _tmpView.center = self.view.center;
        [self.view addSubview:_tmpView];
        [self.view bringSubviewToFront:recordView];
        int x = arc4random() % 100000;
        NSTimeInterval time = [[NSDate date] timeIntervalSince1970];
        NSString *fileName = [NSString stringWithFormat:@"%d%d",(int)time,x];

        [[HDCDDeviceManager sharedInstance] asyncStartRecordingWithFileName:fileName completion:^(NSError *error)
         {
             if (error) {
                 NSLog(@"%@",NSEaseLocalizedString(@"message.startRecordFail", @"failure to start recording"));
             }
         }];
    }
}

- (void)didHdCancelRecordingVoiceAction:(UIView *)recordView
{
    self.maskingView  = [self.view viewWithTag:33];
    [self.maskingView removeFromSuperview];
    [[HDCDDeviceManager sharedInstance] cancelCurrentRecording];
    if ([recordView isKindOfClass:[HDRecordView class]]) {
        [(HDRecordView *)recordView recordButtonTouchUpOutside];
    }
        [recordView removeFromSuperview];

}

- (void)didHdFinishRecoingVoiceAction:(UIView *)recordView
{
    self.maskingView  = [self.view viewWithTag:33];
    [self.maskingView removeFromSuperview];
    if ([recordView isKindOfClass:[HDRecordView class]]) {
        [(HDRecordView *)recordView recordButtonTouchUpInside];
    }

    __weak typeof(self) weakSelf = self;
    [[HDCDDeviceManager sharedInstance] asyncStopRecordingWithCompletion:^(NSString *recordPath, NSInteger aDuration, NSError *error) {
        if (!error) {
            __weak typeof(self) weakSelf = self;
            NSString *fileName =[[recordPath componentsSeparatedByString:@"/"] lastObject];

            NSData *data = [NSData dataWithContentsOfFile:recordPath];
            MBProgressHUD *hud = [MBProgressHUD showMessag:NSLocalizedString(@"uploading...", "Upload attachment") toView:self.view];
            hud.layer.zPosition = 1.f;
            __weak MBProgressHUD *weakHud = hud;
            SCLoginManager *lgM = [SCLoginManager shareLoginManager];
            //此方法只为演示用,用户应把录制的附件放到自己服务器,环信服务器不存储留言的附件
            [[[HChatClient sharedClient] leaveMsgManager] uploadWithTenantId:lgM.tenantId File:data parameters:@{@"fileName":fileName} completion:^(id responseObject, NSError *error) {
                if (!error) {
                    [weakHud hide:YES];
                    if ([responseObject isKindOfClass:[NSDictionary class]]) {
                        LeaveMsgAttachmentModel *attachment = [[LeaveMsgAttachmentModel alloc] initWithDictionary:nil];
                        NSArray * entities = [responseObject objectForKey:@"entities"];
                        if ([entities count] > 0) {
                            NSDictionary *entity = [entities objectAtIndex:0];
                            attachment.url = [NSString stringWithFormat:@"%@/%@",[responseObject objectForKey:@"uri"],[entity objectForKey:@"uuid"]];
                        }
                        attachment.name = fileName;
                        attachment.type = @"audio";
                        attachment.wavDuration =  [NSString stringWithFormat:@"%d",(int)aDuration];
                        [weakSelf.attachments addObject:attachment];
                        [weakSelf _reloadAttatchmentsView];
                    }
                } else {
                    [weakHud setLabelText:NSLocalizedString(@"failed", "Upload attachment failed")];
                    [weakHud hide:YES afterDelay:0.5];
                }
            }];

        }else {
            [weakSelf showHudInView:self.view hint:NSLocalizedString(@"media.timeShort", @"The recording time is too short")];
            self.recordChangeBtn.enabled = NO;
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [weakSelf hideHud];
                self.recordChangeBtn.enabled = YES;
            });
        }
    }];

    [recordView removeFromSuperview];

}

- (void)didHdDragOutsideAction:(UIView *)recordView
{
    if ([recordView isKindOfClass:[HDRecordView class]]) {
        [(HDRecordView *)recordView recordButtonDragInside];
    }
}

- (void)didHdDragInsideAction:(UIView *)recordView
{
    if ([recordView isKindOfClass:[HDRecordView class]]) {
        [(HDRecordView *)recordView recordButtonDragOutside];
    }
}

- (void)dealloc
{
    [self _stopAudioPlayingWithChangeCategory];

    if (_imagePicker){
        [_imagePicker dismissViewControllerAnimated:NO completion:nil];
        _imagePicker = nil;
    }
}

- (void)setupBarButtonItem
{
    CustomButton * backButton = [CustomButton buttonWithType:UIButtonTypeCustom];
    [backButton setImage:[UIImage imageNamed:@"Shape"] forState:UIControlStateNormal];
    [backButton setTitle:NSLocalizedString(@"title.reply", @"Reply") forState:UIControlStateNormal];
    backButton.titleLabel.font = [UIFont systemFontOfSize:18];
    [backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [backButton setTitleColor:RGBACOLOR(184, 22, 22, 1) forState:UIControlStateHighlighted];
    backButton.imageRect = CGRectMake(10, 6.5, 16, 16);
    backButton.titleRect = CGRectMake(28, 0, 83, 29);
    [self.view addSubview:backButton];
    backButton.frame = CGRectMake(0, 0, 120, 29);

    [backButton addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    UIBarButtonItem *nagetiveSpacer = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
    nagetiveSpacer.width = -16;
    self.navigationItem.leftBarButtonItems = @[nagetiveSpacer,backItem];

    UIButton *sendButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
    [sendButton setTitle:NSLocalizedString(@"send", @"Send") forState:UIControlStateNormal];
    [sendButton addTarget:self action:@selector(sendAction) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem *sendItem = [[UIBarButtonItem alloc] initWithCustomView:sendButton];
    UIBarButtonItem *sendNagetiveSpacer = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
    sendNagetiveSpacer.width = -12;
    self.navigationItem.rightBarButtonItems = @[sendNagetiveSpacer,sendItem];
}

- (void)back
{
    [self _stopAudioPlayingWithChangeCategory];
    [self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - getter

- (FLTextView *)textView
{
    if (_textView == nil) {
        _textView = [[FLTextView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight * 0.3)];
        [_textView setPlaceholderText:[NSString stringWithFormat:@"%@%@",NSLocalizedString(@"title.reply", @"Reply"),@"..."]];
        _textView.fontSize = 13.0;
        _textView.font = [UIFont systemFontOfSize:18];
        _textView.layer.borderColor = [UIColor clearColor].CGColor;
        _textView.returnKeyType = UIReturnKeyDone;
        _textView.delegate = self;
        UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(_textView.frame), kScreenWidth, 0.5f)];
//        line.backgroundColor = [UIColor lightGrayColor];
        [self.view addSubview:line];
    }
    return _textView;
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    if ([text isEqualToString:@"\n"]) {
        [self restoreButton];
        [self.recordButtonView removeFromSuperview];
        self.recordChangeBtn.selected = NO;
        [_textView endEditing:YES];
        return NO;
    }
    return YES;
}

- (UIButton*)addButton
{

    if (_addButton == nil) {
        _addButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _addButton.size = CGSizeMake(30, 30);
        _addButton.center = CGPointMake(kScreenWidth/2 + kScreenWidth/3 - 10, kScreenHeight - 90);
        [_addButton setImage:[UIImage imageNamed:@"HelpDeskUIResource.bundle/hd_chatting_setmode_attachment_btn_normal"] forState:UIControlStateNormal];
        [_addButton addTarget:self action:@selector(addAction) forControlEvents:UIControlEventTouchUpInside];
    }
    return _addButton;
}

- (UIImagePickerController *)imagePicker
{
    if (_imagePicker == nil) {
        _imagePicker = [[UIImagePickerController alloc] init];
        _imagePicker.delegate = self;
    }

    return _imagePicker;
}

- (NSMutableArray*)attachments
{
    if (_attachments == nil) {
        _attachments = [NSMutableArray array];
    }
    return _attachments;
}

- (UIScrollView*)attchmentView
{
    if (_attchmentView == nil) {
        _attchmentView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, kScreenHeight - 170, kScreenWidth * 0.6, 100)];
        _attchmentView.showsVerticalScrollIndicator = YES;
        _attchmentView.indicatorStyle = UIScrollViewIndicatorStyleDefault;
        _attchmentView.directionalLockEnabled = YES;
    }
    return _attchmentView;
}

#pragma mark - action

- (void)sendAction
{
    [self _stopAudioPlayingWithChangeCategory];
    if (_textView.text.length == 0 && _attachments.count == 0) {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"prompta", @"Prompt") message:NSLocalizedString(@"leaveMessage.leavemsg.replyempty", @"Reply is empty") delegate:self cancelButtonTitle:NSLocalizedString(@"ok", @"OK") otherButtonTitles:nil, nil];
        [alertView show];
        return;
    }

    if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectSendButtonWithParameters:)]) {
        NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
        NSMutableArray *attachments = [NSMutableArray array];
        for (LeaveMsgAttachmentModel *attachment in _attachments) {
            [attachments addObject:[attachment getContent]];
        }
        [parameters setObject:attachments forKey:@"attachments"];

        [parameters setObject:_textView.text forKey:@"content"];
        [self.delegate didSelectSendButtonWithParameters:parameters];
    }
}

//添加图片
- (void)addAction
{
    _recordChangeBtn.selected = NO;
    [_recordButtonView removeFromSuperview];
    [self restoreButton];
    [self _stopAudioPlayingWithChangeCategory];
    self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    self.imagePicker.mediaTypes = @[(NSString *)kUTTypeImage];
    [self presentViewController:self.imagePicker animated:YES completion:NULL];
}

#pragma mark - UIImagePickerControllerDelegate

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    NSString *mediaType = info[UIImagePickerControllerMediaType];
    if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
        UIImage *orgImage = info[UIImagePickerControllerOriginalImage];
        NSURL *imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];

        __weak typeof(self) weakSelf = self;
        MBProgressHUD *hud = [MBProgressHUD showMessag:NSLocalizedString(@"uploading...", "Upload attachment") toView:self.view];
        hud.layer.zPosition = 1.f;
        __weak MBProgressHUD *weakHud = hud;
        ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset) {
            ALAssetRepresentation *representation = [myasset defaultRepresentation];
            NSString *fileName = [representation filename];
            NSData *data =UIImageJPEGRepresentation(orgImage, 0.5);

            SCLoginManager *lgM = [SCLoginManager shareLoginManager];
            ////此方法只为演示用,用户应把录制的附件放到自己服务器,环信服务器不存储留言的附件
            [[[HChatClient sharedClient] leaveMsgManager] uploadWithTenantId:lgM.tenantId File:data parameters:@{@"fileName":fileName} completion:^(id responseObject, NSError *error) {
                if (!error) {
                    [weakHud hide:YES];
                    if ([responseObject isKindOfClass:[NSDictionary class]]) {
                        LeaveMsgAttachmentModel *attachment = [[LeaveMsgAttachmentModel alloc] initWithDictionary:nil];
                        NSArray * entities = [responseObject objectForKey:@"entities"];
                        if ([entities count] > 0) {
                            NSDictionary *entity = [entities objectAtIndex:0];
                            attachment.url = [NSString stringWithFormat:@"%@/%@",[responseObject objectForKey:@"uri"],[entity objectForKey:@"uuid"]];
                        }
                        attachment.name = fileName;
                        attachment.type = @"image";
                        [weakSelf.attachments addObject:attachment];
                        [weakSelf _reloadAttatchmentsView];
                    }
                } else {
                    [weakHud setLabelText:NSLocalizedString(@"failed", "Upload attachment failed")];
                    [weakHud hide:YES afterDelay:0.5];
                }
            }];

        };
        ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
        [assetslibrary assetForURL:imageURL
                       resultBlock:resultblock
                      failureBlock:nil];
        [picker dismissViewControllerAnimated:YES completion:nil];
    }
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [self.imagePicker dismissViewControllerAnimated:YES completion:nil];

}

#pragma mark - LeaveMsgAttatchmentViewDelegate

- (void)didRemoveAttatchment:(NSInteger)index
{
    index = index -baseTag;
    if ([_attachments count] > index) {
        [_attachments removeObjectAtIndex:index];
        [self _reloadAttatchmentsView];
    }
    [self clearTempWav];
}

- (void)_reloadAttatchmentsView
{
    for (UIView *subView in [_attchmentView subviews]) {
        [subView removeFromSuperview];
    }

    CGFloat left = kDefaultLeft;
    CGFloat height = 10;
    NSInteger index = 0;
    for (LeaveMsgAttachmentModel *attachment in self.attachments) {
        if (left + [LeaveMsgAttatchmentView widthForName:attachment.name maxWidth:kScreenWidth*0.6 - kDefaultLeft - 10] > kScreenWidth*0.6) {
            left = kDefaultLeft;
            height += 50;
        }

        LeaveMsgAttatchmentView *attatchmentView = [[LeaveMsgAttatchmentView alloc] initWithFrame:CGRectMake(left, height, [LeaveMsgAttatchmentView widthForName:attachment.name maxWidth:kScreenWidth*0.6 - kDefaultLeft - 10], 30) edit:YES model:attachment];
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAttatchmentAction:)];
        tap.delegate = attatchmentView;
        tap.cancelsTouchesInView = NO;
        [attatchmentView addGestureRecognizer:tap];
        attatchmentView.delegate = self;
        attatchmentView.tag = index+baseTag;
        [_attchmentView addSubview:attatchmentView];
        index ++;
        left += [LeaveMsgAttatchmentView widthForName:attachment.name maxWidth:kScreenWidth*0.6 - kDefaultLeft - 10] + kDefaultLeft + 10;
    }
    [_attchmentView setContentSize:CGSizeMake(kScreenWidth*0.6, height + 10.f)];
}

#pragma mark - action

- (void)tapAttatchmentAction:(UITapGestureRecognizer *)sender
{
    UITapGestureRecognizer *tap = (UITapGestureRecognizer*)sender;
    NSInteger index = tap.view.tag-baseTag;
    if ([_attachments count] > index) {
        LeaveMsgAttachmentModel *attachment = [_attachments objectAtIndex:index];
        if ([attachment.type isEqualToString:@"image"]) {
            [[HDMessageReadManager defaultManager] showBrowserWithImages:@[[NSURL URLWithString:attachment.url]]];
        }
        if ([attachment.type isEqualToString:@"audio"]) {
            LeaveMsgAttatchmentView *view = (LeaveMsgAttatchmentView *)tap.view;
            _currentAnimationView = view;
            kWeakSelf
            [[[HChatClient sharedClient] leaveMsgManager] downloadFileWithUrl:attachment.url completionHander:^(BOOL success, NSURL *filePath, NSError *error) {
                if (!error) {
                    NSString *toPath = [NSString stringWithFormat:@"%@/%ld.wav",NSTemporaryDirectory(),tap.view.tag];
                    BOOL success = [[HDCDDeviceManager new] convertAMR:[filePath path] toWAV:toPath];
                    if (success) {
                        [weakSelf playWithfilePath:toPath];
                    }
                }else{

                    NSLog(@"下载文件失败");
                }
            }];
        }
    }
}
- (void)playWithfilePath:(NSString *)path {
    NSData *data = [NSData dataWithContentsOfFile:path];
    NSFileManager *fm = [NSFileManager defaultManager];
    if ([fm fileExistsAtPath:path]) {
        [fm removeItemAtPath:path error:nil];
    }
    _audioPlayer = [SCAudioPlay sharedInstance];
    _audioPlayer.delegate = self;
    if (_audioPlayer.isPlaying) {
        [_audioPlayer stopSound];
    }
    [_audioPlayer playSoundWithData:data];
}

- (void)AVAudioPlayerBeiginPlay {
    if (_audioPlayer.attatchmentView != nil) {
        [_audioPlayer.attatchmentView stopAnimating];
    }
    _audioPlayer.attatchmentView = _currentAnimationView;;
    [_currentAnimationView startAnimating];
}

- (void)AVAudioPlayerDidFinishPlay {
    [_currentAnimationView stopAnimating];
}

- (void)clearTempWav {
    NSString *cachesPath = NSTemporaryDirectory();
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *contents = [fileManager contentsOfDirectoryAtPath:cachesPath error:NULL];
    NSEnumerator *e = [contents objectEnumerator];
    NSString *filename;
    while ((filename = [e nextObject])) {
        if ([[filename pathExtension] isEqualToString:@"wav"]) {
            BOOL success =  [fileManager removeItemAtPath:[cachesPath stringByAppendingPathComponent:filename] error:NULL];
            if (success) {
                NSLog(@"success");
            }
        }
    }
}

+ (void)resetFile {
    NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *contents = [fileManager contentsOfDirectoryAtPath:cachesPath error:NULL];
    NSEnumerator *e = [contents objectEnumerator];
    NSString *filename;
    while ((filename = [e nextObject])) {
        if ([[filename pathExtension] isEqualToString:@"amr"]) {
            BOOL success =  [fileManager removeItemAtPath:[cachesPath stringByAppendingPathComponent:filename] error:NULL];
            if (success) {
                NSLog(@"success");
            }
        }
    }
}

- (void)move
{
    [self hide];
    _recordChangeBtn.originY = _recordChangeBtn.frame.origin.y - _boardHeight;
    _addButton.originY = _addButton.frame.origin.y - _boardHeight;
    [self scrollViewAsTheKeyboardMove];
}

- (void)hide
{
    _recordChangeBtn.center = CGPointMake(kScreenWidth/2 + kScreenWidth/3 + 30, kScreenHeight - 90);
    _addButton.center = CGPointMake(kScreenWidth/2 + kScreenWidth/3 - 10, kScreenHeight - 90);
    [self scrollViewAsTheButtonMove];
}

- (void)restoreButton
{
    _recordChangeBtn.center = CGPointMake(kScreenWidth/2 + kScreenWidth/3 + 30, kScreenHeight - 90);
    _addButton.center = CGPointMake(kScreenWidth/2 + kScreenWidth/3 - 10, kScreenHeight - 90);
    [self scrollViewFrame];

}

- (void)scrollViewAsTheButtonMove
{
    [self scrollViewFrame];
}

- (void)scrollViewAsTheKeyboardMove
{
    _attchmentView.originY = _attchmentView.frame.origin.y - _boardHeight;
}

- (void)scrollViewHide
{
    [self scrollViewFrame];
}

- (void)scrollViewFrame
{
    _attchmentView.originX = 0;
    _attchmentView.originY = kScreenHeight - 170;
}

- (void)_stopAudioPlayingWithChangeCategory
{
    //停止音频播放及播放动画
    if (_audioPlayer.isPlaying) {
        [_audioPlayer stopSound];
    }
    if (_audioPlayer.attatchmentView != nil) {
        [_audioPlayer.attatchmentView stopAnimating];
    }
}

@end


text:
<?php namespace Icy;
use Illuminate\Support\ServiceProvider;

/**
 * Created by PhpStorm.
 * User: Chad
 * Date: 10/13/2014
 * Time: 2:21 AM
 */

class VendorServiceProvider extends ServiceProvider {

	protected $defer = true;

	/**
	 * Register the service provider.
	 *
	 * @return void
	 */
	public function register()
	{
		$this->app->bind('GuzzleHttp\ClientInterface', function ($app)
		{
			return $app->make('GuzzleHttp\Client');
		});
	}

	public function provides()
	{
		return ['GuzzleHttp\ClientInterface'];
	}

}


text:
class Debunker
  class Command::Stat < Debunker::ClassCommand
    match 'stat'
    group 'Introspection'
  #'View method information and set _file_ and _dir_ locals.'
    command_options :shellwords => false

    banner <<-'BANNER'
        Usage: stat [OPTIONS] [METH]

        Show method information for method METH and set _file_ and _dir_ locals.

        stat hello_method
    BANNER

    def options(opt)
      method_options(opt)
    end

    def process
      meth = method_object
      aliases = meth.aliases

      output.puts unindent <<-EOS
        Method Information:
        --
        Name: #{meth.name}
        Alias#{ "es" if aliases.length > 1 }: #{ aliases.any? ? aliases.join(", ") : "None." }
        Owner: #{meth.owner ? meth.owner : "Unknown"}
        Visibility: #{meth.visibility}
        Type: #{meth.is_a?(::Method) ? "Bound" : "Unbound"}
        Arity: #{meth.arity}
        Method Signature: #{meth.signature}
        Source Location: #{meth.source_location ? meth.source_location.join(":") : "Not found."}
      EOS
    end
  end

  Debunker::Commands.add_command(Debunker::Command::Stat)
end


text:
CREATE TABLE aa(a);
CREATE TABLE bb(b);
INSERT INTO aa VALUES(1);
INSERT INTO aa VALUES(3);
INSERT INTO bb VALUES(2);
INSERT INTO bb VALUES(4);
SELECT * FROM aa, bb WHERE max(a,b)>2;


text:
package sun.management.snmp.jvmmib;

//
// Generated by mibgen version 5.0 (06/02/03) when compiling JVM-MANAGEMENT-MIB in standard metadata mode.
//

// jmx imports
//
import com.sun.jmx.snmp.SnmpStatusException;

/**
 * This interface is used for representing the remote management interface for the "JvmRTInputArgsEntry" MBean.
 */
public interface JvmRTInputArgsEntryMBean {

    /**
     * Getter for the "JvmRTInputArgsItem" variable.
     */
    public String getJvmRTInputArgsItem() throws SnmpStatusException;

    /**
     * Getter for the "JvmRTInputArgsIndex" variable.
     */
    public Integer getJvmRTInputArgsIndex() throws SnmpStatusException;

}


text:
require 'pl'
utils.import 'pl.func'
local ops = require 'pl.operator'
local List = require 'pl.List'
local append,concat = table.insert,table.concat
local compare,find_if,compare_no_order,imap,reduce,count_map = tablex.compare,tablex.find_if,tablex.compare_no_order,tablex.imap,tablex.reduce,tablex.count_map

function bindval (self,val)
    rawset(self,'value',val)
end

local optable = ops.optable

function sexpr (e)
	if isPE(e) then
		if e.op ~= 'X' then
			local args = tablex.imap(sexpr,e)
			return '('..e.op..' '..table.concat(args,' ')..')'
		else
			return e.repr
		end
	else
		return tostring(e)
	end
end

psexpr = compose(print,sexpr)

function equals (e1,e2)
    local p1,p2 = isPE(e1),isPE(e2)
    if p1 ~= p2 then return false end  -- different kinds of animals!
    if p1 and p2 then -- both PEs
        -- operators must be the same
        if e1.op ~= e2.op then return false end
        -- PHs are equal if their representations are equal
        if e1.op == 'X' then return e1.repr == e2.repr
        -- commutative operators
        elseif e1.op == '+' or e1.op == '*' then
            return compare_no_order(e1,e2,equals)
        else
            -- arguments must be the same
            return compare(e1,e2,equals)
        end
    else -- fall back on simple equality for non PEs
        return e1 == e2
    end
end

-- run down an unbalanced operator chain (like a+b+c) and return the arguments {a,b,c}
function tcollect (op,e,ls)
    if isPE(e) and e.op == op then
        for i = 1,#e do
            tcollect(op,e[i],ls)
        end
    else
        ls:append(e)
        return
    end
end

function rcollect (e)
    local res = List()
    tcollect(e.op,e,res)
    return res
end

-- balance ensures that +/* chains are collected together, operates in-place.
-- thus (+(+ a b) c) or (+ a (+ b c)) becomes (+ a b c), order immaterial
function balance (e)
    if isPE(e) and e.op ~= 'X' then
        local op,args = e.op
        if op == '+' or op == '*' then
            args = rcollect(e)
        else
            args = imap(balance,e)
        end
        for i = 1,#args do
            e[i] = args[i]
        end
    end
    return e
end

-- fold constants in an expression
function fold (e)
    if isPE(e) then
        if e.op == 'X' then
            -- there could be _bound values_!
            local val = rawget(e,'value')
            return val and val or e
        else
            local op = e.op
            local addmul = op == '*' or op == '+'
            -- first fold all arguments
            local args = imap(fold,e)
            if not addmul and not find_if(args,isPE) then
                -- no placeholders in these args, we can fold the expression.
                local opfn = optable[op]
                if opfn then
                    return opfn(unpack(args))
                else
                    return '?'
                end
            elseif addmul then
                -- enforce a few rules for + and *
                -- split the args into two classes, PE args and non-PE args.
                local classes = List.partition(args,isPE)
                local pe,npe = classes[true],classes[false]
                if npe then -- there's at least one non PE argument
                    -- so fold them
                    if #npe == 1 then npe = npe[1]
                    else npe = npe:reduce(optable[op])
                    end
                    -- if the result is a constant, return it
                    if not pe then return npe end

                    -- either (* 1 x) => x or (* 1 x y ...) => (* x y ...)
                    if op == '*' then
                        if npe == 0 then return 0
                        elseif npe == 1 then -- identity
                            if #pe == 1 then return pe[1] else npe = nil end
                        end
                    else -- special cases for +
                        if npe == 0 then -- identity
                            if #pe == 1 then return pe[1] else npe = nil end
                        end
                    end
                end
                -- build up the final arguments
                local res = {}
                if npe then append(res,npe) end
                for val,count in pairs(count_map(pe,equals)) do
                    if count > 1 then
                        if op == '*' then val = val ^ count
                        else val = val * count
                        end
                    end
                    append(res,val)
                end
                if #res == 1 then return res[1] end
                return PE{op=op,unpack(res)}
            elseif op == '^' then
                if args[2] == 1 then return args[1] end -- identity
                if args[2] == 0 then return 1 end
            end
            return PE{op=op,unpack(args)}
        end
    else
        return e
    end
end

function expand (e)
    if isPE(e) and e.op == '*' and isPE(e[2]) and e[2].op == '+' then
        local a,b = e[1],e[2]
        return expand(b[1]*a) + expand(b[2]*a)
    else
        return e
    end
end

function isnumber (x)
    return type(x) == 'number'
end

-- does this PE contain a reference to x?
function references (e,x)
    if isPE(e) then
        if e.op == 'X' then return x.repr == e.repr
        else
            return find_if(e,references,x)
        end
    else
        return false
    end
end

local function muli (args)
    return PE{op='*',unpack(args)}
end

local function addi (args)
    return PE{op='+',unpack(args)}
end

function diff (e,x)
    if isPE(e) and references(e,x) then
        local op = e.op
        if op == 'X' then
            return 1
        else
            local a,b = e[1],e[2]
            if op == '+' then -- differentiation is linear
                local args = imap(diff,e,x)
                return balance(addi(args))
            elseif op == '*' then -- product rule
                local res,d,ee = {}
                for i = 1,#e do
                    d = fold(diff(e[i],x))
                    if d ~= 0 then
                        ee = {unpack(e)}
                        ee[i] = d
                        append(res,balance(muli(ee)))
                    end
                end
                if #res > 1 then return addi(res)
                else return res[1] end
            elseif op == '^' and isnumber(b) then -- power rule
                return b*x^(b-1)
            end
        end
    else
        return 0
    end
end


text:
package net.imagej.ui.swing.overlay;

import net.imagej.display.ImageDisplay;

import org.jhotdraw.draw.BezierFigure;
import org.jhotdraw.draw.DrawingView;
import org.jhotdraw.draw.tool.BezierTool;

/**
 * A JHotDraw {@link BezierTool} for ImageJ's Swing UI.
 *
 * @author Lee Kamentsky
 * @author Johannes Schindelin
 */
public class IJBezierTool extends BezierTool implements JHotDrawTool {

	private final ImageDisplay display;
	private final JHotDrawAdapter<BezierFigure> adapter;

	public IJBezierTool(final ImageDisplay display,
		final JHotDrawAdapter<BezierFigure> adapter)
	{
		super((BezierFigure) adapter.createDefaultFigure());
		this.display = display;
		this.adapter = adapter;
	}

	// -- BezierTool methods --

	@Override
	protected BezierFigure createFigure() {
		return (BezierFigure) getAdapter().createDefaultFigure();
	}

	@Override
	protected void finishCreation(final BezierFigure figure,
		final DrawingView drawingView)
	{
		super.finishCreation(figure, drawingView);
		final JHotDrawService jHotDrawService =
			getDisplay().getContext().getService(JHotDrawService.class);
		jHotDrawService.linkOverlay(figure, getAdapter(), getDisplay());
	}

	// -- JHotDrawTool methods --

	@Override
	public ImageDisplay getDisplay() {
		return display;
	}

	@Override
	public JHotDrawAdapter<BezierFigure> getAdapter() {
		return adapter;
	}

	@Override
	public boolean isConstructing() {
		return createdFigure != null;
	}

}


text:
package com.github.assisstion.ModulePack.collection.wrapper;

import java.util.ListIterator;

public class ListIteratorWrapper<T> extends AbstractWrapper<ListIterator<T>> implements ListIterator<T>{

	protected ListIterator<T> wrapped;

	public ListIteratorWrapper(ListIterator<T> listIterator){
		wrapped = listIterator;
	}

	@Override
	public boolean hasNext(){
		return get().hasNext();
	}

	@Override
	public T next(){
		return get().next();
	}

	@Override
	public boolean hasPrevious(){
		return get().hasPrevious();
	}

	@Override
	public T previous(){
		return get().previous();
	}

	@Override
	public int nextIndex(){
		return get().nextIndex();
	}

	@Override
	public int previousIndex(){
		return get().previousIndex();
	}

	@Override
	public void remove(){
		get().remove();
	}

	@Override
	public void set(T e){
		get().set(e);
	}

	@Override
	public void add(T e){
		get().add(e);
	}

	@Override
	public ListIterator<T> get(){
		return wrapped;
	}

}


text:
namespace Jasily.Linq.Expressions.Cache
{
    public static class Extensions
    {
        public static TTo ConvertChecked<TFrom, TTo>(this TFrom source)
            => Cache.ConvertChecked<TFrom, TTo>.Func(source);

        public static TTo ConvertUnchecked<TFrom, TTo>(this TFrom source)
            => Cache.ConvertUnchecked<TFrom, TTo>.Func(source);
    }
}


text:
// Generated by LiveScript 1.4.0

(function(){
  Polymer({
    is: 'cs-blogs-admin-sections-add-edit-form',
    behaviors: [cs.Polymer.behaviors.Language('blogs_')],
    properties: {
      section: Object,
      original_title: String,
      sections: Array
    },
    ready: function(){
      var this$ = this;
      Promise.all([
        this.id
          ? cs.api('get api/Blogs/admin/sections/' + this.id)
          : {
            title: '',
            path: '',
            parent: 0
          }, cs.api('get api/Blogs/admin/sections')
      ]).then(function(arg$){
        var sections;
        this$.section = arg$[0], sections = arg$[1];
        this$.original_title = this$.section.title;
        this$.sections = sections;
      });
    },
    _save: function(){
      var method, suffix, this$ = this;
      method = this.id ? 'put' : 'post';
      suffix = this.id ? '/' + this.id : '';
      cs.api(method + " api/Blogs/admin/sections" + suffix, this.section).then(function(result){
        cs.ui.notify(this$.L.changes_saved, 'success', 5);
      });
    }
  });
}).call(this);


text:
package dataExtensibility;

/**
 * The base class of all expression forms
 */
public abstract class Expr {

	/*
	 * Operation for pretty printing
	 */
	public abstract String prettyPrint();

	/*
	 * Operation for expression evaluation
	 */
	public abstract int evaluate();
}


text:
package com.example.android.leanback;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

/**
 * Sample PlaybackSeekDataProvider render time label as thumb.
 */
class PlaybackSeekDataProviderSample extends PlaybackSeekAsyncDataProvider {

    Paint mPaint;

    PlaybackSeekDataProviderSample(long duration, long interval) {
        int size = (int) (duration / interval) + 1;
        long[] pos = new long[size];
        for (int i = 0; i < pos.length; i++) {
            pos[i] = i * duration / pos.length;
        }
        setSeekPositions(pos);
        mPaint = new Paint();
        mPaint.setTextSize(16);
        mPaint.setColor(Color.BLUE);
    }

    protected Bitmap doInBackground(Object task, int index, long position) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException ex) {
            // Thread might be interrupted by cancel() call.
        }
        if (isCancelled(task)) {
            return null;
        }
        Bitmap bmp = Bitmap.createBitmap(160, 160, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bmp);
        canvas.drawColor(Color.YELLOW);
        canvas.drawText(formatTime(position), 10, 80, mPaint);
        canvas.drawText(Integer.toString(index), 10, 150, mPaint);
        return bmp;
    }

    String formatTime(long ms) {
        long seconds = ms / 1000;
        float seconds2 = (ms - seconds * 1000) / 1000f;
        long minutes = seconds / 60;
        long hours = minutes / 60;
        seconds -= minutes * 60;
        minutes -= hours * 60;

        StringBuilder b = new StringBuilder();
        if (hours > 0) {
            b.append(hours).append(':');
            if (minutes < 10) {
                b.append('0');
            }
        }
        b.append(minutes).append(':');
        if (seconds < 10) {
            b.append('0');
        }
        b.append(String.format("%.2f", ((float) seconds + seconds2)));
        return b.toString();
    }

}


text:
<head>
    <style>
        * {
            background-color: green;
       }

        #game {
            border: 3px solid black;
            background-color: white;
 position: relative;
 transform:    translateX(50%);
 max-width: 480;
 max-height: 360;
        }
    </style>

    <object id=game width="50%" height="50%">
        <param name="movie" value="https://ongaming.github.io/Left.Aligned.v1.0.swf">
        <embed src="https://ongaming.github.io/Left.Aligned.v1.0.swf" width="50%" height="50%">
        </embed>
    </object>
</head>