Makale Özeti

Bu makalemde sizlerle beraber vCalendar,iCalendar dosyasının ne olduğunu, ne iş yaptığını, standartlarını inceledikten sonra bu dosyayı standartlara uygun bir şekilde oluşturan bir class file yazıp uygulamalarımıza nasıl değer katabileceğimiz üzerinde duracağız.

Makale

          Merhabalar,         

          Bu makalemde sizlerle beraber vCalendar,iCalendar dosyasının ne olduğunu, ne iş yaptığını, standartlarını inceledikten sonra bu dosyayı standartlara uygun bir şekilde oluşturan bir class file yazıp uygulamalarımıza nasıl değer katabileceğimiz üzerinde duracağız.          Internet Mail Consortium (IMC) tarafından hazırlanan standart bir format olan vCalendar'ın yeni versiyonu olarak karşımıza çıkan iCalendar(RFC 2445) daha fazla özellik barındırabilmekte ve daha çok platform tarafından desteklenmektedir.Bu iki versiyon arasındaki farklılıkları aşağıdaki tabloda daha detaylı görebilirsiniz.

  vCalendar iCalendar
Descripton: vCalendar iCalendar
Uzantı: .vcs .ics
MIME tipi: text/x-vCalendar text/Calendar


         vCalendar'ın versiyon numarası 1.0 iken iCalendar'ın versiyon numarası 2.0 dır.Bunu yazacağımız kodun içinde de göreceğiz. Peki bir vcalendar dosyası neleri içerir. Şimdi bunu inceleyelim,

         vCalendar : Çekirdek obje olan bu tanımlama tüm ics ve vcs dosyalarında bulunmalı ve diğer nesneler hiyerarşik olarak bu nesnenin child'ları olarak bulunmalıdır.
         vEvent : Bu obje eventların tanımlandığı kod bloğudur. Bir vCalendar dosyası birden fazla event barındırabilir. Eventlar Meeting Requestler veya Appointmentlar gibi Takvim entryleri olabilmektedir.
         vAlarm : Bu obje uygulamalar tarafından verilecek alarmların belirlendiği nesnedir. Bir calendar nesnesi içinde bulunan eventlarda birden fazla alarm nesnesi barındırabilmektedir.
         vTODO : Bu obje ise yapılacak işlerin tutulduğu calendar nesnesidir. Bu makalede incelemeyeceğiz ancak bulunduğunu bilmekte fayda var.

         Yukarıda bahsettiğim objeler dışında vJournal gibi objelerde vardır ancak bu dosyarak IMC(Internet Mail Consortium) tarafından yayınlanmış olan Specification dökümanında bulunmamaktadır.

         Şimdi bahsettiğimiz vCalendar dosyasını oluşturacak class'ımızı yazmaya başlayalım. Sizinde tahmin edebileceğiniz gibi class dosyamızda Calendar,Event,Alarm nesneleri bulunacaktır. Bu nesnelerin herbirinde bize istediğimiz dosya içeriğini string'e çeviren metodlar olacaktır.

         vAlarm Nesnesi Özellikleri :

TRIGGER : Alarmın event başlamadan ne kadar önce tetikleneceği bilgisinin tutulduğu alan. Örn: Eventtan 3 saat önce haber verilmesi için -PT180M kullanılabilir.
ACTION : Alarmın devreye girdiği zaman yapacağı aksiyon. Genellikle DISPLAY kullanılır.
DESCRIPTION : Alarmın açıklaması. Varsayılan olarak Reminder kullanılır.

         Örnek olarak oluşturulmuş bir vAlarm dosyasını icf dosyasının içinde inceleyecek olursak. Aşağıdaki gibi bir yapıyla karşılaşırız.
BEGIN:VALARM
TRIGGER:-PT15M
ACTION:DISPLAY
DESCRIPTION:Reminder
END:VALARM
         Burada görmüş olduğunuz gibi vAlarm dosyasının başlangıç ve bitiş tagları arasında eventtan 15 dakika önce alarmın devreye gireceği belirtilmiş. Ayrıca Aksiyon olarak display ve Dipslay olarakda Reminder seçilmiş durumda.

         Şimdi bu kodu oluşturabilecek classımızı yazalım.
    public class vAlarm
    {
        #region members
        private TimeSpan _Trigger = new TimeSpan(0, 15, 0);
        private string _Action = "DISPLAY";
        private string _Description = "Reminder";
        #endregion
 
        #region properties
        public TimeSpan Trigger
        {
            get { return _Trigger; }
            set { _Trigger = value; }
        }
        public string Action
        {
            get { return _Action; }
            set { _Action = value; }
        }
        public string Description
        {
            get { return _Description; }
            set { _Description = value; }
        }
        #endregion
 
        #region ctors
        public vAlarm()
        {
            _Trigger = TimeSpan.FromMinutes(30);
            _Action = "DISPLAY";
            _Description = "Reminder";
        }
        public vAlarm(TimeSpan parTrigger, string parAction, string parDescription)
        {
            _Trigger = parTrigger;
            _Action = parAction;
            _Description = parDescription;
        }
        #endregion
 
        #region methods
        public string GetVAlarm()
        {
            StringBuilder insStringBuilder = new StringBuilder();
            insStringBuilder.Append("BEGIN:VALARM");
            insStringBuilder.Append(System.Environment.NewLine);
 
            insStringBuilder.Append("TRIGGER:-PT");
            insStringBuilder.Append(Trigger.TotalMinutes);
            insStringBuilder.Append("M");
            insStringBuilder.Append(System.Environment.NewLine);
 
            insStringBuilder.Append("ACTION:");
            insStringBuilder.Append(Action);
            insStringBuilder.Append(System.Environment.NewLine);
 
            insStringBuilder.Append("DESCRIPTION:");
            insStringBuilder.Append(Description);
            insStringBuilder.Append(System.Environment.NewLine);
 
            insStringBuilder.Append("END:VALARM");
            insStringBuilder.Append(System.Environment.NewLine);
 
            return insStringBuilder.ToString();
        }
        #endregion
    }

         Kodda görebileceğiniz gibi vAlarm nesnesinin yukarıda bahsettiğimiz her özelliğini taşıyabilecek bir member değişken bulunmaktadır. Bu değişkenler encapsule edilerek propertyler oluşturulmuştur. Burada önemli nokta Trigger propertysinin alarmın kaç dakika önce devreye gireceğini belirlediğinden tipinin TimeSpan olmasıdır. Ctor region'u içinde ise 2 adet yapıcı metod bulunmaktadır. Bunlardan bir tanesi parametrik değer almayan ve property'lere varsayılan değerleri atayan, diğeri ise tüm propertylere atanacak değerleri parametrik olarak alandır. Atadığımız bu propertylerden vAlarm nesnesini oluşturmak için çağıracağımız metod ise GetVAlarm() metodudur. Esasında bu metodun yaptığı işe bakacak olursak. String birleştirme işlemi ile yukarıda verdiğimiz örnek vAlarm nesnesini strin olarak bize geri döndürdüğünü göreceğiz. Uygun propertylerin değerleri uygun yerlere konularak string birleştirilmekte ve sonucunda bize vAlarm nesnesini dosya içinde ifade eden string döndürülmektedir.

         Şimdi ise isterseniz event bilgilerinin tutulduğu vEvent yapısını inceleyelim.

         vEvent nesnesi Özellikleri:

ATTENDEE : Event'a katılacak kişilerin bilgilerinin tutulduğu kısımdır. Kişinin görünen Adı, Optional veya Required olduğu ve mail adresi bu özellik içinde tutulur.
ORGANIZER : Event'ı organize eden kişidir. Mail adresi yazılabilir.
DTSTART : Event'ın başlayacağı tarihin tutulduğu alandır.
DTEND : Event'ın biteceği tarihin tutulduğu alandır.
LOCATION : Eventın lokasyon olarak nerede yapılacağının tutulduğu alandır.
UID : Event için tanımlanmış Unique bir identifierdır.
DTSTAMP : Eventın oluşturulduğu tarihtir.
SUMMARY : Eventın bir özetini yazabileceğiniz alandır.
VALARM : Event'a ait alamların tanımlanması için kullanılabilecek bir alandır.
         
         Şimdi ise Örnek bir VCalendar dosyasını inceleyelim.
BEGIN:VEVENT
ATTENDEE;CN="Tamer Öz";ROLE=OPT-PARTICIPANT;RSVP=TRUE:MAILTO:oztamer@hotmail.com
ORGANIZER:MAILTO:oztamer@hotmail.com
DTSTART:20070318T053000Z
DTEND:20070318T060000Z
LOCATION:OrnekLokasyon
UID:040000008200E00074C5B7101A82E00800000000F02A48732E69C7010000000000000000100
 000009D259B8FF3265F4E91F5106CD696CB28
DTSTAMP:20070318T053110Z
SUMMARY:Baslık
BEGIN:VALARM
TRIGGER:-PT15M
ACTION:DISPLAY
DESCRIPTION:Reminder
END:VALARM
END:VEVENT
         Yukarıda görebileceğiniz gibi esasında anlaşılırlığı gayet basit olan bir format. Açıklamak gerekirse. Attendee kısmında event'a katılacak olan kişilerin bilgilerini giriyoruz. Burada İsmini,Optional mı Required mı olduğu bilgilerini ve mail adresinin her Attendee için girebiliyoruz. Bu dosya birden fazla Attendee satırı barındırabilir bir formattadır. Organizer kısmına ise event'ı organize eden kişinin mail adresini yazıyoruz. DTStart ve DTEnd kısımlarına ise event'ın başlangıç ve bitiş tarihlerini giriyoruz.Location kısmına eventın nerede yapılacağı bilgisi yer almaktadır.UID unique bir key olarak event'ı unique'leştirmeye yarar. Eventin ne zaman oluşturulduğu bilgiside girildikten sonra Summary alanına özet bilgiler girilmektedir. ve görebileceğiniz gibi bir önceki kısımda oluşturmuş olduğumuz VAlarm içeriğini vEvent'ın içine olduğu gibi koymamız gerekmektedir.

         Şimdi bu kodu oluşturabilecek Class'ımızı yazalım.
    public class vEvent
    {
        private List<Attendee> _Attendees = new List<Attendee>();
        private DateTime _DateTimeStart;
        private DateTime _DateTimeEnd;
        private string _Summary;
        private string _Organizer;
        private string _Location;
        private string _Description;
        private List<vAlarm> _Alarms = new List<vAlarm>();
 
        public List<Attendee> Attendees
        {
            get { return _Attendees; }
        }
        public DateTime DateTimeStart
        {
            get { return _DateTimeStart; }
            set { _DateTimeStart = value; }
        }
        public DateTime DateTimeEnd
        {
            get { return _DateTimeEnd; }
            set { _DateTimeEnd = value; }
        }
        public string Summary
        {
            get { return _Summary; }
            set { _Summary = value; }
        }
        public string Organizer
        {
            get { return _Organizer; }
            set { _Organizer = value; }
        }
        public string Location
        {
            get { return _Location; }
            set { _Location = value; }
        }
        public string Description
        {
            get { return _Description; }
            set { _Description = value; }
        }
        public List<vAlarm> Alarms
        {
            get { return _Alarms; }
        }
 
        public string GetVEvent()
        {
            StringBuilder insStringBuilder = new StringBuilder();
            insStringBuilder.Append("BEGIN:VEVENT");
            insStringBuilder.Append(System.Environment.NewLine);
 
            foreach (Attendee insAttendee in Attendees)
            {
                insStringBuilder.Append(@"ATTENDEE;CN=""");
                insStringBuilder.Append(insAttendee.Name);
                insStringBuilder.Append(@""";ROLE=");
                insStringBuilder.Append(insAttendee.Role.ToString());
                insStringBuilder.Append(@"-PARTICIPANT;RSVP=TRUE:MAILTO:");
                insStringBuilder.Append(insAttendee.Mail);
                insStringBuilder.Append(System.Environment.NewLine);
            }
 
            insStringBuilder.Append("UID:");
            insStringBuilder.Append(Guid.NewGuid().ToString());
            insStringBuilder.Append(System.Environment.NewLine);
 
            insStringBuilder.Append("SUMMARY:");
            insStringBuilder.Append(Summary);
            insStringBuilder.Append(System.Environment.NewLine);
 
            insStringBuilder.Append("ORGANIZER:MAILTO:");
            insStringBuilder.Append(Organizer);
            insStringBuilder.Append(System.Environment.NewLine);
 
            insStringBuilder.Append("LOCATION:");
            insStringBuilder.Append(Location);
            insStringBuilder.Append(System.Environment.NewLine);
 
            insStringBuilder.Append("DTSTART:");
            insStringBuilder.Append(DateTimeStart.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"));
            insStringBuilder.Append(System.Environment.NewLine);
 
            insStringBuilder.Append("DTEND:");
            insStringBuilder.Append(DateTimeEnd.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"));
            insStringBuilder.Append(System.Environment.NewLine);
 
            insStringBuilder.Append("DTSTAMP:");
            insStringBuilder.Append(DateTime.Now.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"));
            insStringBuilder.Append(System.Environment.NewLine);
 
            insStringBuilder.Append("DESCRIPTION:");
            insStringBuilder.Append(Description);
            insStringBuilder.Append(System.Environment.NewLine);
 
 
            foreach (vAlarm insVAlarm in Alarms)
            {
                insStringBuilder.Append(insVAlarm.GetVAlarm());
            }
 
            insStringBuilder.Append("END:VEVENT");
            insStringBuilder.Append(System.Environment.NewLine);
 
            return insStringBuilder.ToString();
        }
    }
          Kodda görebileceğiniz gibi vEvent nesnesinin yukarıda bahsettiğimiz her özelliğini taşıyabilecek bir member değişken bulunmaktadır. Bu değişkenler encapsule edilerek propertyler oluşturulmuştur.Dikkat edilmesi gereken noktalardan bir tanesi Attendee nesnesinin nasıl tanımlanacağı ve nasıl ekleneceğidir. Attendee nesnesinin yapısı Gözüken Ad, Katılım Türü(OPT,REQ) ve mail adresi barındıran basit bir yapı olduğundan kod içinde yazılmamış ve açıklanmamıştır.Örnek Uygulamayı İndirip inceleyebilirsiniz. Dosyanın oluşturulma ve kodun çalışma mantığı olarak vAlarm Nesnesinden bir farklı bulunmamaktadır.  Uygun propertylerin değerleri uygun yerlere konularak string birleştirilmekte ve sonucunda bize vEvent nesnesini dosya içinde ifade eden string döndürülmektedir.

         Şimdi isterseniz  temel nesnemiz olan vCalendar nesnemizi inceleyelim.

         vCalendar Nesnesi Yapısı:
VERSION : Oluşturacak olan dosyanın versiyonu. Esasında makalenin başında bahsettiğim gibi oluşturulacak olan dosyanın 1.0 olan vCalendar dosyası mı yoksa 2.0 olan iCalendar dosyası mı olacağı bilgisidir.
METHOD : Oluşturulacak olan dosyanın bir Event mı yoksa bir Meeting Request mi olduğu bilgisidir. Event için PUBLISH kullanılırken Meeting Request için REQUEST kullanılmalıdır.
         Şimdi örnek bir vCalendar dosyasını inceleyelim.
BEGIN:VCALENDAR
VERSION:2.0
METHOD:REQUEST
BEGIN:VEVENT
ATTENDEE;CN="Tamer Öz";ROLE=OPT-PARTICIPANT;RSVP=TRUE:MAILTO:oztamer@hotmail.com
ORGANIZER:MAILTO:oztamer@hotmail.com
DTSTART:20070318T053000Z
DTEND:20070318T060000Z
LOCATION:OrnekLokasyon
UID:040000008200E00074C5B7101A82E00800000000F02A48732E69C7010000000000000000100
000009D259B8FF3265F4E91F5106CD696CB28
DTSTAMP:20070318T053110Z
SUMMARY:Baslık
BEGIN:VALARM
TRIGGER:-PT15M
ACTION:DISPLAY
DESCRIPTION:Reminder
END:VALARM
END:VEVENT
END:VCALENDAR
         Bir önceki adımda oluşturduğumuz vEvent dosyasını barındıracak şekilde ve sadece Version ve Method özelliklerini ekleyerek yeni bir dosya oluşturursak bu ulaşmamız gereken vCalendar veya iCalendar dosyası olacaktır.

         En son olarak bize vCalendar Dosyasını oluşturabilecek Class dosyamızı yazalım.
    public class vCalendar
    {
        private List<vEvent> _Events = new List<vEvent>();
        private enmCalendarType _CalendarType;
 
        public List<vEvent> Events
        {
            get { return _Events; }
        }
        public enmCalendarType CalendarType
        {
            get { return _CalendarType; }
            set { _CalendarType = value; }
        }
 
        public string GetVCalendar()
        {
            StringBuilder insStringBuilder = new StringBuilder();
            insStringBuilder.Append("BEGIN:VCALENDAR");
            insStringBuilder.Append(System.Environment.NewLine);
 
            insStringBuilder.Append("VERSION:2.0");
            insStringBuilder.Append(System.Environment.NewLine);
 
            insStringBuilder.Append("METHOD:");
            insStringBuilder.Append(this.CalendarType.ToString());
            insStringBuilder.Append(System.Environment.NewLine);
 
            foreach (vEvent insVEvent in Events)
            {
                insStringBuilder.Append(insVEvent.GetVEvent());
            }
 
            insStringBuilder.Append("END:VCALENDAR");
            insStringBuilder.Append(System.Environment.NewLine);
 
            return insStringBuilder.ToString();
        }
 
        public vCalendar()
        {
            CalendarType = enmCalendarType.REQUEST;
        }
    }
          Kod içerisinde de görebileceğiniz gibi biraz önce bahsettiğimiz. özellikleri string olarak ekledikten sonra her event nesnesini dosyanın içine oluşturarak vCalendar nesnemizi kaydedebiliriz.

         Şimdi isterseniz bir calendar dosyasının kod tarafından nasıl oluşturulacağına bakalım.

            vAlarm al = new vAlarm();
            al.Trigger = new TimeSpan(1, 0, 0);
           
            vEvent ev = new vEvent();
            ev.Alarms.Add(al);
            ev.Attendees.Add(new Attendee("Tamer Öz", enmRole.REQ, "oztamer@hotmail.com"));
            ev.DateTimeStart=DateTime.Now;
            ev.DateTimeEnd = DateTime.Now.AddHours(3);
            ev.Description = "Deneme Kaydi";
            ev.Location = "Ofiste";
            ev.Organizer = "oztamer@hotmail.com";
            ev.Summary = "Ozet Bilgi";
 
            vCalendar cal = new vCalendar();
            cal.Events.Add(ev);
 
            FileStream fs = new FileStream(@"C:\makale.ics", FileMode.Create, FileAccess.ReadWrite);
            Encoding iso = Encoding.GetEncoding("iso-8859-9");
            byte[] aaa = iso.GetBytes(cal.GetVCalendar());
 
            fs.Write(aaa, 0, aaa.Length);
            fs.Close();
         
         Gördüğünüz gibi artık çok basit bir kullanımla kendi vCalendar dosyamızı oluşturabiliyoruz. Meeting request gönderebilmemiz için tek yapmamız gereken bu dosyanın mail içeriği olarak gönderilmesidir.
         Umarım projelerinizde kullanabileceğiniz bir makale olmuştur.

         oztamer@hotmail.com
         tamer.oz@yazgelistir.com
         oztamer@hotmail.com
 
Ornek Kodlar