Exercise 6: Solution

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Plato.Core;

namespace Plato.Language
{
    /// <summary>
    /// An entity token represents an entity.
    /// </summary>
    public class EntityToken : Token, IPropertyPathToken, IOutputPropertyPathToken
    {
        private IEntity entity;

        public EntityToken(IEntity entity)
            : base(TokenType.Entity)
        {
            Util.NotNull(entity);

            this.entity = entity;
        }

        public IEntity Entity
        {
            get { return entity; }
        }

        public override string ToString()
        {
            return entity.Id;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Plato.Core;

namespace Plato.Language
{
    /// <summary>
    /// An entity token represents an entity.
    /// </summary>
    public class EntityToken : Token, IPropertyPathToken, IOutputPropertyPathToken
    {
        private IEntity entity;

        public EntityToken(IEntity entity)
            : base(TokenType.Entity)
        {
            Util.NotNull(entity);

            this.entity = entity;
        }

        public IEntity Entity
        {
            get { return entity; }
        }

        public override string ToString()
        {
            return entity.Id;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Plato.Core;

namespace Plato.Language
{
    /// <summary>
    /// An entity type token acts as a wildcard. The satisfying
    /// entity must have an "is_a" relationship with the specified
    /// type.
    /// </summary>
    public class EntityTypeToken : Token, IInputToken
    {
        private IEntity entity;

        public EntityTypeToken(IEntity entity)
            : base(TokenType.EntityType)
        {
            Util.NotNull(entity);

            this.entity = entity;
        }

        /// <summary>
        /// The entity type.
        /// </summary>
        public IEntity Entity
        {
            get { return entity; }
        }

        public override string ToString()
        {
            return entity.Id;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Plato.Language
{
    /// <summary>
    /// A fragment consists of one or more tokens, but can
    /// serve as a token itself.
    /// </summary>
    public class Fragment : Token
    {
        private IList<IToken> tokens;

        public Fragment(IList<IToken> tokens)
            : base(TokenType.Fragment)
        {
            this.tokens = tokens;
        }

        public IList<IToken> Tokens
        {
            get { return tokens; }
        }

        public override string ToString()
        {
            string[] tokenList = new string[tokens.Count];

            for (int i = 0; i < tokens.Count; ++i)
            {
                tokenList[i] = tokens[i].ToString();

                switch (tokens[i].TokenType)
                {
                    case TokenType.Literal:
                    case TokenType.Variable:
                        tokenList[i] = tokenList[i].ToString();
                        break;
                    case TokenType.Entity:
                    case TokenType.Property:
                        tokenList[i] = "[" + tokenList[i].ToString() + "]";
                        break;
                    case TokenType.EntityType:
                        tokenList[i] = "{" + tokenList[i].ToString() + "}";
                        break;
                    default:
                        throw new NotImplementedException(tokens[i].TokenType.ToString());
                }
            }

            return String.Join(" ", tokenList);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Plato.Core;

namespace Plato.Language
{
    /// <summary>
    /// A fragment token represents a fragment.
    /// </summary>
    public class FragmentToken : Token, IPropertyPathToken
    {
        private Fragment fragment;

        public FragmentToken(Fragment fragment)
            : base(TokenType.Fragment)
        {
            Util.NotNull(fragment);

            this.fragment = fragment;
        }

        public Fragment Fragment
        {
            get { return fragment; }
        }

        public override string ToString()
        {
            return fragment.ToString();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Plato.Language
{
    public interface IInputToken : IToken
    {
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Plato.Language
{
    public interface IOutputPropertyPathToken : IPropertyPathToken
    {
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Plato.Language
{
    public interface IPropertyPathToken : IToken
    {
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Plato.Language
{
    public interface IToken
    {
        TokenType TokenType
        {
            get;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Plato.Core;

namespace Plato.Language
{
    /// <summary>
    /// A literal token represents a string/word.
    /// </summary>
    public class LiteralToken : Token, IInputToken
    {
        private string str;

        public LiteralToken(string str)
            : base(TokenType.Literal)
        {
            Util.NotNull(str);

            this.str = str;
        }

        public string String
        {
            get { return str; }
        }

        public override string ToString()
        {
            return str;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Plato.Core;

namespace Plato.Language
{
    public class PropertyToken : Token
    {
        private IList<IPropertyPathToken> path;

        public PropertyToken(IList<IPropertyPathToken> path)
            : base(TokenType.Property)
        {
            Util.NotNull(path);

            this.path = path;
        }

        public override string ToString()
        {
            string[] tokenList = new string[path.Count];

            for (int i = 0; i < path.Count; ++i)
            {
                tokenList[i] = path[i].ToString();

                switch (path[i].TokenType)
                {
                    case TokenType.Entity:
                    case TokenType.Variable:
                        tokenList[i] = tokenList[i].ToString();
                        break;
                    case TokenType.Fragment:
                        tokenList[i] = "((" + tokenList[i].ToString() + "))";
                        break;
                    default:
                        throw new NotImplementedException(path[i].TokenType.ToString());
                }
            }

            return String.Join(".", tokenList);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Plato.Language
{
    /// <summary>
    /// Fragments and properties are broken down into a list
    /// of tokens.
    /// </summary>
    public abstract class Token : IToken
    {
        private TokenType tokenType;

        public Token(TokenType tokenType)
        {
            this.tokenType = tokenType;
        }

        public TokenType TokenType
        {
            get { return tokenType; }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Plato.Language
{
    public enum TokenType
    {
        Literal,
        EntityType,
        Entity,
        Fragment,
        Variable,
        Property
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Plato.Core;

namespace Plato.Language
{
    public class Transformation
    {
        private TransInput input;
        private ITransOutput output;

        public Transformation(TransInput input, ITransOutput output)
        {
            Util.NotNull(input, output);

            this.input = input;
            this.output = output;
        }

        public TransInput Input
        {
            get { return input; }
        }

        public ITransOutput Output
        {
            get { return output; }
        }

        public override string ToString()
        {
            return input.ToString() + " -> " + output.ToString();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Plato.Core;

namespace Plato.Language
{
    public class TransInput
    {
        private IList<IInputToken> tokens;

        public TransInput(IList<IInputToken> tokens)
        {
            if (tokens == null)
            {
                throw new ArgumentNullException("tokens");
            }

            if (tokens.Count == 0)
            {
                throw new Exception("Empty token list.");
            }

            this.tokens = tokens;
        }

        public IList<IInputToken> Tokens
        {
            get { return tokens; }
        }

        public override string ToString()
        {
            string[] tokenList = new string[tokens.Count];

            for (int i = 0; i < tokens.Count; ++i)
            {
                tokenList[i] = tokens[i].ToString();

                switch (tokens[i].TokenType)
                {
                    case TokenType.Literal:
                        tokenList[i] = tokenList[i].ToString();
                        break;
                    case TokenType.EntityType:
                        tokenList[i] = "{" + tokenList[i].ToString() + "}";
                        break;
                    default:
                        throw new NotImplementedException(tokens[i].TokenType.ToString());
                }
            }

            return String.Join(" ", tokenList);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Plato.Core;

namespace Plato.Language
{
    public interface ITransOutput
    {
    }

    /// <summary>
    /// A transformation's output specification for an assignment.
    /// </summary>
    public class TransOutput_Assignment : ITransOutput
    {
        private PropertyToken property;
        private VariableToken value;

        public TransOutput_Assignment(PropertyToken property, VariableToken value)
        {
            Util.NotNull(property, value);

            this.property = property;
            this.value = value;
        }
    }

    /// <summary>
    /// A transformation's output specification for a property/value.
    /// </summary>
    public class TransOutput_Value : ITransOutput
    {
        private PropertyToken property;

        public TransOutput_Value(PropertyToken property)
        {
            Util.NotNull(property);

            this.property = property;
        }

        public PropertyToken Property
        {
            get { return property; }
        }

        public override string ToString()
        {
            return property.ToString();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Plato.Language
{
    /// <summary>
    /// A variable token represents the ID of the entity that resolves
    /// an EntityTypeToken. The variable number is used to uniquely specify
    /// the EntityTypeToken.
    /// </summary>
    public class VariableToken : Token, IOutputPropertyPathToken
    {
        private uint variableNumber;

        public VariableToken(uint variableNumber)
            : base(TokenType.Variable)
        {
            this.variableNumber = variableNumber;
        }

        public uint VariableNumber
        {
            get { return variableNumber; }
        }

        public override string ToString()
        {
            return "$" + variableNumber;
        }
    }
}