public static string GetInterfaces( Extension extension, DataModel model )
 {
     var dataObject = new {
                      _foreignTable = NameHelper.GetAbsoluteModelName( extension, model )
                    };
       return Interfaces.FormatSmart( dataObject );
 }
        /// <summary>
        /// Resolves the models of an extension from a ParsedPartial.
        /// </summary>
        /// <param name="parsedFragment">The partially parsed extension.</param>
        /// <returns>The models of the extension</returns>
        public static List<DataModel> Resolve( Fragment parsedFragment )
        {
            IEnumerable<Fragment> modelPartials = parsedFragment.Fragments.Where( p => p.Keyword == Keywords.ExtensionDirectives.DeclareModel );
              if( !modelPartials.Any() ) return null;

              List<DataModel> dataModels = new List<DataModel>();
              foreach( Fragment modelPartial in modelPartials ) {
            DataModel dataModel = new DataModel {Name = modelPartial.Parameters, SourceFragment = modelPartial};
            dataModels.Add( dataModel );
            if( modelPartial.Fragments.Any() ) {
              foreach( Fragment dataMember in modelPartial.Fragments ) {
            if( dataMember.Keyword == Keywords.InternalType ) {
              dataModel.InternalType = dataMember.Parameters;

            } else {
              dataModel.Members.Add(
                new DataModel.DataModelMember {Name = dataMember.Keyword, Value = dataMember.Parameters} );
            }
              }
            }
              }

              // Resolve any foreign key references
              ForeignKeyResolver.Resolve( dataModels );

              return dataModels;
        }
        private string GenerateSqlMembers( DataModel dataModel )
        {
            StringBuilder dataMembers = new StringBuilder();
              StringBuilder keys = new StringBuilder();
              foreach( DataModel.DataModelMember member in dataModel.Members ) {
            // Is this a template request or a normal data member?
            if( Keywords.DataModelTemplate == member.Name ) {
              switch( member.Value ) {
            case Keywords.DataModelTemplates.T3ManagedFields:
              dataMembers.Append( T3ManagedFields.Content + ",\n" );
              keys.Append( T3ManagedFields.Keys + ",\n" );
              break;

            case Keywords.DataModelTemplates.T3CommonFields:
              dataMembers.Append( T3CommonFields.Content + ",\n" );
              break;

            case Keywords.DataModelTemplates.T3VersioningFields:
              dataMembers.Append( T3VersioningFields.Content + ",\n" );
              keys.Append( T3VersioningFields.Keys + ",\n" );
              break;

            case Keywords.DataModelTemplates.T3TranslationFields:
              dataMembers.Append( T3TranslationFields.Content + ",\n" );
              keys.Append( T3TranslationFields.Keys + ",\n" );
              break;

            case Keywords.DataModelTemplates.T3Sortable:
              dataMembers.Append( T3Sortable.Content + ",\n" );
              break;

            default:
              throw new GeneratorException(
                string.Format( "Data model template '{0}' is unknown", member.Value ),
                dataModel.SourceFragment.SourceDocument );
              }
            } else {
              if( dataModel.ForeignModels.ContainsKey( member.Value ) ) {
            // For a foreign key, we just insert the default uint
            dataMembers.Append(
              string.Format(
                "{0} {1},\n", NameHelper.GetSqlColumnName( Subject, member.Value ),
                TypeTranslator.ToSQL( Keywords.Types.UnsignedInt, dataModel.SourceFragment.SourceDocument ) ) );

              } else if( TypeTranslator.CanTranslate( member.Name ) ) {
            // If it is a POD type, just translate it
            dataMembers.Append(
              string.Format(
                "{0} {1},\n", NameHelper.GetSqlColumnName( Subject, member.Value ),
                TypeTranslator.ToSQL( member.Name, dataModel.SourceFragment.SourceDocument ) ) );

              } else {
            throw new GeneratorException(
              string.Format( "Data model field type '{0}' in model '{1}' is unknown.", member.Name, dataModel.Name ),
              dataModel.SourceFragment.SourceDocument );
              }
            }
              }
              String dataMembersAndKeys = string.Format(
            "{0},\n{1}", (dataMembers.Length >0) ? dataMembers.ToString().Substring( 0, dataMembers.Length - 2 ) : string.Empty,
            ( keys.Length > 0 ) ? keys.ToString().Substring( 0, keys.Length - 2 ) : string.Empty );

              return dataMembersAndKeys;
        }
        /// <summary>
        /// Generates an ExtBase repository for the given data model.
        /// This allows ExtBase controllers to retrieve data records from the database.
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        /// <exception cref="GeneratorException">Implementation for repository does not exist.</exception>
        private string GenerateRepositoryFile( DataModel model )
        {
            const string repositoryImplementationTemplate = "private $implementation;\n" +
                                                      "private function getImplementation() {{\n" +
                                                      "  if( null == $this->implementation ) {{\n" +
                                                      "    $this->implementation = new {implClassname}($this);\n" +
                                                      "  }}\n" +
                                                      "  return $this->implementation;\n" +
                                                      "}}\n";

              string implementationClassname = NameHelper.GetExtbaseDomainModelRepositoryImplementationClassName( Subject, model );
              string implementationFilename  = NameHelper.GetExtbaseDomainModelRepositoryImplementationFileName( Subject, model );
              string baseClassname           = "Tx_Extbase_Persistence_Repository";

              // Did the user define additional information for our repository
              bool isExternallyImplemented = false;
              Repository repositoryDefinition = Subject.Repositories.SingleOrDefault( r => r.TargetModelName == model.Name );

              // If the repository type is an internal type, no need to generate anything...
              if( null != repositoryDefinition && !string.IsNullOrEmpty( repositoryDefinition.InternalType ) ) {
            // ...unless BOTH an internal type and an implementation are given
            if( !string.IsNullOrEmpty( repositoryDefinition.Implementation ) ) {
              // This would indicate that the internal type is to be extended by the implementation
              // A common example of this is the extension of the Tx_Extbase_Domain_Repository_FrontendUserRepository
              baseClassname = repositoryDefinition.InternalType;

            } else {
              return string.Empty;
            }
              }

              if( null != repositoryDefinition && !string.IsNullOrEmpty( repositoryDefinition.Implementation ) ) {
            if( !File.Exists( repositoryDefinition.Implementation ) ) {
              throw new GeneratorException(
            string.Format(
              "Implementation '{0}' for repository for '{1}' does not exist.", repositoryDefinition.Implementation,
              model.Name ),
            repositoryDefinition.SourceFragment.SourceDocument );
            }

            isExternallyImplemented = true;

            Log.InfoFormat( "Merging implementation '{0}'...", repositoryDefinition.Implementation );
            string repositoryImplementationContent = File.ReadAllText( repositoryDefinition.Implementation );
            DateTime lastWriteTimeUtc = new FileInfo( repositoryDefinition.Implementation ).LastWriteTimeUtc;
            if( !Regex.IsMatch( repositoryImplementationContent, String.Format( "class {0} ?({{|extends|implements)", implementationClassname ) ) ) {
              Log.WarnFormat( "The class name of your implementation for repository for model '{1}' MUST be '{0}'!", implementationClassname, repositoryDefinition.TargetModelName );
            }

            WriteFile( "Classes/Domain/Repository/" + implementationFilename, repositoryImplementationContent, lastWriteTimeUtc );
              }

              // Generate methods as described in definition
              StringBuilder actions = new StringBuilder();
              if( null != repositoryDefinition ) {
            const string actionTemplate = "public function {0}({1}) {{ return $this->getImplementation()->{0}({1}); }}\n";

            foreach( Action action in repositoryDefinition.Methods ) {
              // Prefix each parameter with a $ and join them together with , in between.
              string parameters = action.Requirements.Aggregate(
            string.Empty,
            ( current, requirement ) =>
            current + ( "$" + requirement + ( ( requirement != action.Requirements.Last() ) ? "," : string.Empty ) ) );

              actions.Append( String.Format( actionTemplate, action.Name, parameters ) );
            }
              }

              string repositoryImplementation =
            repositoryImplementationTemplate.FormatSmart(
              new {
                implClassname = implementationClassname,
                className     = NameHelper.GetExtbaseDomainModelRepositoryClassName( Subject, model )
              } );

              // Generate final class
              const string template = "class {_className} extends {_baseClass} {{\n" +
                              "{_repositoryMethods}\n" +
                              "}}\n" +
                              "{_requireImplementation}";

              return
            template.FormatSmart(
              new {
                _className             = NameHelper.GetExtbaseDomainModelRepositoryClassName( Subject, model ),
                _baseClass             = baseClassname,
                _repositoryMethods     = repositoryImplementation + actions,
                _requireImplementation = ( isExternallyImplemented ) ? string.Format( "require_once('{0}');\n", implementationFilename ) : string.Empty
              } );
        }
        /// <summary>
        /// Generate the ExtBase model file for the given data model.
        /// </summary>
        /// <param name="dataModel"></param>
        /// <returns></returns>
        private string GenerateModelFile( DataModel dataModel )
        {
            // If this model implements an internal type, we don't need to generate anything.
              if( !string.IsNullOrEmpty( dataModel.InternalType ) ) {
            return string.Empty;
              }

              const string template =
            "class {className} extends Tx_Extbase_DomainObject_AbstractEntity {{\n" +
            "{properties}" +
            "{gettersSetters}" +
            "}}";

              const string propertyTemplate = "/**\n" +
                                      "* {0}\n" +
                                      "* @var {1}\n" +
                                      "*/\n" +
                                      "protected ${0};\n";

              StringBuilder dataMembers = new StringBuilder();
              foreach( DataModel.DataModelMember member in dataModel.Members ) {
            if( member.Name == Keywords.DataModelTemplate ) continue;
            bool containsKey = dataModel.ForeignModels.ContainsKey( member.Value );
            if( containsKey ) {
              DataModel foreignModel = dataModel.ForeignModels[ member.Value ];
              // Make sure to use the internal type name if it is defined.
              string foreignModelClassName = foreignModel.InternalType
                                         ??
                                         NameHelper.GetExtbaseDomainModelClassName( Subject, dataModel.ForeignModels[ member.Name ] );
              dataMembers.Append( string.Format( propertyTemplate, member.Value, foreignModelClassName ) );

            } else {
              dataMembers.Append( string.Format( propertyTemplate, member.Value, TypeTranslator.ToPHP( member.Name, dataModel.SourceFragment.SourceDocument ) ) );
            }

              }

              const string accessor = "public function get{1}() {{" +
                              "	 return $this->{0};" +
                              "}}" +
                              "public function set{1}( ${0} ) {{" +
                              "	 $this->{0} = ${0};" +
                              "}}\n";

              StringBuilder accessors = new StringBuilder();
              foreach( DataModel.DataModelMember member in dataModel.Members ) {
            accessors.Append( string.Format( accessor, member.Value, NameHelper.UpperCamelCase( member.Value ) ) );
              }

              var dataObject = new {
                             className = NameHelper.GetExtbaseDomainModelClassName( Subject, dataModel ),
                             properties = dataMembers,
                             gettersSetters = accessors
                           };

              return template.FormatSmart( dataObject );
        }
        /// <summary>
        /// Generates a placeholder Fluid partial that will render a given data model.
        /// </summary>
        /// <param name="dataModel"></param>
        /// <returns></returns>
        private string GenerateFluidPartial( DataModel dataModel )
        {
            const string modelTemplate               = "<div class=\"tx-{cssRoot}-item\">\n{fieldsList}</div>\n";
              const string fieldTemplate               = "<div>{{{fieldAccessor}}}</div>\n";

              StringBuilder fieldsCollector = new StringBuilder();
              foreach( DataModel.DataModelMember member in dataModel.Members ) {
            fieldsCollector.Append( fieldTemplate.FormatSmart( new {fieldAccessor = dataModel.Name + "." + member.Value} ) );
              }
              string fields = fieldsCollector.ToString();

              string model =
            modelTemplate.FormatSmart(
              new {fieldsList = fields, cssRoot = NameHelper.UpperCamelCase( Subject.Key ).ToLower()} );

              return model;
        }
 /// <summary>
 /// Generates the Extbase class name for a given data model.
 /// </summary>
 /// <param name="extension"></param>
 /// <param name="dataModel"></param>
 /// <returns></returns>
 public static string GetExtbaseDomainModelFileName( Extension extension, DataModel dataModel )
 {
     return String.Format( "{0}.php", UpperCamelCase( dataModel.Name ) );
 }
 /// <summary>
 /// Generates the ExtBase domain model class name for a given data model.
 /// </summary>
 /// <param name="extension"></param>
 /// <param name="dataModel"></param>
 /// <returns></returns>
 public static string GetExtbaseDomainModelClassName( Extension extension, DataModel dataModel )
 {
     return String.Format( "Tx_{0}_Domain_Model_{1}", UpperCamelCase( extension.Key ), UpperCamelCase( dataModel.Name ) );
 }
 /// <summary>
 /// Retrieves a full model name for a data model.
 /// </summary>
 /// <example>
 /// tx_downloads_domain_model_download
 /// </example>
 /// <param name="extension">The extension this data model belongs to.</param>
 /// <param name="model">The data model.</param>
 /// <returns></returns>
 public static string GetAbsoluteModelName( Extension extension, DataModel model )
 {
     return String.Format( "tx_{0}_domain_model_{1}", extension.Key.Replace( "_", string.Empty ), model.Name.ToLower() );
 }
 /// <summary>
 /// Generates the file name for a Fluid partial.
 /// </summary>
 /// <param name="subject"></param>
 /// <param name="dataModel"></param>
 /// <returns></returns>
 public static string GetFluidPartialFileName( Extension subject, DataModel dataModel )
 {
     return String.Format( "{0}.html", UpperCamelCase( dataModel.Name ) );
 }
 /// <summary>
 /// Generates the Extbase class name for a given data model repository implementation.
 /// </summary>
 /// <param name="extension"></param>
 /// <param name="dataModel"></param>
 /// <returns></returns>
 public static string GetExtbaseDomainModelRepositoryImplementationFileName( Extension extension, DataModel dataModel )
 {
     return String.Format( "{0}RepositoryImplementation.php", UpperCamelCase( dataModel.Name ) );
 }
 /// <summary>
 /// Generates the ExtBase domain model repository class name for a given data model that must be used for a specific implementation.
 /// </summary>
 /// <param name="extension"></param>
 /// <param name="dataModel"></param>
 /// <returns></returns>
 public static string GetExtbaseDomainModelRepositoryImplementationClassName( Extension extension, DataModel dataModel )
 {
     return String.Format( "{0}{1}RepositoryImplementation", UpperCamelCase( extension.Key ), UpperCamelCase( dataModel.Name ) );
 }