/**
 * Creates a SymmetryElement from a SymmetryOperation
 *
 * As detailed in the class description, the method checks whether there is
 * already a prototype SymmetryElement for the provided SymmetryOperation. If
 * not, it tries to find an appropriate generator and uses that to create
 * the prototype. Then it returns a clone of the prototype.
 *
 * @param operation :: SymmetryOperation for which to generate the element.
 * @return SymmetryElement for the supplied operation.
 */
SymmetryElement_sptr SymmetryElementFactoryImpl::createSymElement(
    const SymmetryOperation &operation) {
  std::string operationIdentifier = operation.identifier();

  SymmetryElement_sptr element = createFromPrototype(operationIdentifier);

  if (element) {
    return element;
  }

  AbstractSymmetryElementGenerator_sptr generator = getGenerator(operation);

  if (!generator) {
    throw std::runtime_error("Could not process symmetry operation '" +
                             operationIdentifier + "'.");
  }

  insertPrototype(operationIdentifier, generator->generateElement(operation));

  return createFromPrototype(operationIdentifier);
}