a148c3064436804a7ea190718e94620ce5aa8b11
[sitecorepy.git] / sitecore / prof / __init__.py
1 #!/usr/bin/env python
2 # Copyright (C) 2010 W. Trevor King <wking@drexel.edu>
3 #
4 # This file is part of SiteCorePy.
5 #
6 # SiteCorePy is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License as published by the
8 # Free Software Foundation, either version 2 of the License, or (at your
9 # option) any later version.
10 #
11 # SiteCorePy is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with SiteCorePy.  If not, see <http://www.gnu.org/licenses/>.
18
19 """
20 Sitecore Faculty Profile        Corresponding Information
21
22 Faculty Information
23 -------------------
24 Degrees*        Degrees Earned (i.e. Dr., PhD)
25 College*        University Graduated From
26 Program Area Within Department (i.e. Anthropology)
27 Office* Office Location
28 Office Hours    (If applicable)
29 Specialization* Research Areas/Specialization
30 Publications    Publications Listing (If applicable)
31 Professional Society    (If applicable)
32 Academic Distinctions   (If applicable)
33 Research Interests      (Please use "Specialization" Field)
34 Personal Site   Website Address[b] (If applicable)
35
36 Personal Profile
37 ----------------
38 Title*  Professional Title (i.e. Director of Publication Management)
39 First Name*     First Name / Middle Name
40 Last Name*      Last Name
41 Bio     Brief Bio/Profile/Blurb
42 Short Bio       Presentations (If applicable)
43 Headshot*       Photograph - Size should be width: 125px height: 150px 
44 Email*  Email
45 Phone*  Phone # - Please use this format: (111) 111-1111
46 Fax     Lab Name, Lab Phone (If applicable, please use "Lab Name, Lab Phone" format)
47 CV      Resume
48
49 * field required.
50
51 [b] You can list both "Group website" and "Personal website" under
52  "Personal Site" in the Faculty Profiles.  For example:
53     Group Website: <a href="http://..."">http://...</a><br/>
54     Personal Website: <a href="http://...">http://...</a><br/>
55
56 If a basic text field (a field with no "editor") has more than one
57 item in it then separate the items with a comma (or pipe symbols:
58 |). For example: If a faculty member has more than one title, then
59 list their titles like this: Professor of Communication, Director of
60 Publication Management, Yearbook Advisor, etc.
61 """
62
63 class AttributeHolder (object):
64     fields = []
65
66     def __init__(self, *args, **kwargs):
67         for field in self.fields:
68             setattr(self, field, None)
69         for field,arg in zip(self.fields, args):
70             setattr(self, field, arg)
71         for field,value in kwargs.items():
72             assert field in self.fields, '%s not in %s' % (field, self.fields)
73             setattr(self, field, value)
74
75     def __str__(self):
76         return self.__unicode__()
77
78     def __repr__(self):
79         return '<%s>' % self.__unicode__().replace('\n',';')
80
81     def __unicode__(self):
82         lines = ['%s:' % self.__class__.__name__]
83         for field in self.fields:
84             value = getattr(self, field)
85             if value == None:
86                 continue
87             if isinstance(value, (tuple, list)):
88                 for v in value:
89                     lines.extend(self._format_value(field, v))
90             else:
91                 lines.extend(self._format_value(field, value))
92         return u'\n'.join(lines)
93
94     def _format_value(self, field, value):
95         value_lines = unicode(value).splitlines()
96         if isinstance(value, AttributeHolder):
97             prefix = '  '
98         else:
99             prefix = '  %s: ' % field
100         return ['%s%s' % (prefix, L) for L in value_lines]
101
102 class Name (AttributeHolder):
103     fields = ['first_middle', 'last']
104
105 class Graduation (AttributeHolder):
106     fields = ['college', 'field', 'title', 'year']
107
108 class Contact (AttributeHolder):
109     fields = ['office', 'email', 'website', 'group_site',
110               'phone', 'lab', 'lab_phone']
111
112 class Bio (AttributeHolder):
113     fields = ['category', 'specialization', 'publications', 'profile', 'cv']
114
115 class Professor (AttributeHolder):
116     fields = ['name', 'title', 'graduations', 'contact', 'bio']
117
118     def degrees(self):
119         if self.graduations in [None, []]:
120             return None
121         degrees = [g.title for g in self.graduations]
122         masks = {
123             'M.S.':['B.S.', 'B.A.', 'B.M.'],
124             'Ph.D.':['M.S.', 'M.A.', 'M.Phil.'],
125             }
126         # Princeton uses 'S.M.', 'A.B.', ... instead of 'M.S.', 'B.A.', ... 
127         def princeton_title(title):
128             if m[:2] in ['B.', 'M.']:
129                 fields = title.split('.')
130                 assert (len(fields) == 3 and fields[2] == ''), \
131                     '%s -> %s\n%s' % (title, fields, self.name)
132                 return '.'.join([fields[1], fields[0]] + fields[2:])
133             return title
134         for title,masked in masks.items():
135             ms = list(masked)
136             for m in ms:
137                 pt = princeton_title(m)
138                 if pt != m and pt not in masked:
139                     masked.append(pt)
140             pt = princeton_title(title)
141             if pt not in masks:
142                 masks[pt] = masked
143         masks['Ph.D.'].extend(masks['M.S.'])
144         masks['M.A'] = masks['M.Phil'] = masks['M.S.']
145         for title,masked in masks.items():        
146             if title in degrees:
147                 for m in masked:
148                     if m in degrees:
149                         degrees.remove(m)
150         return '|'.join(degrees)
151
152     def colleges(self):
153         titles = self.degrees().split('|')
154         return '|'.join([g.college for g in self.graduations
155                          if g.title in titles])
156
157     def program(self):
158         "Sub-field(s)"
159         if self.contact.group_site == None:
160             return 'Physics'
161         #TODO: group to sub-field logic
162
163     def sites(self):
164         if self.contact.group_site == None:
165             return ('<a href="%s">%s</a>'
166                     % (self.contact.website, self.contact.website))
167         return ('Group Website: <a href="%s">%s</a>|Personal Website: <a href="%s">%s</a>'
168                 % (self.contact.group_site, self.contact.group_site,
169                    self.contact.website, self.contact.website))
170
171     def lab_contact(self):
172         "Lab Name, Lab Phone"
173         if self.contact.lab != None:
174             assert self.contact.lab_phone != None, unicode(self.name)
175             return '%s, %s' % (self.contact.lab, self.contact.lab_phone)
176         assert self.contact.lab_phone == None, unicode(self.name)
177         return None
178
179     def profile(self):
180         if self.bio.profile == None:
181             return None
182         return ''.join(['<p>\n%s\n</p>\n' % p
183                         for p in prof.bio.profile.split('\n')])