#/**
# *
# * Licensed under the Apache License, Version 2.0 (the "License");
# * you may not use this file except in compliance with the License.
# * You may obtain a copy of the License at
# *
# * http://www.apache.org/licenses/LICENSE-2.0
# *
# * Unless required by applicable law or agreed to in writing, software
# * distributed under the License is distributed on an "AS IS" BASIS,
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# * See the License for the specific language governing permissions and
# * limitations under the License.
# *
# */
import logging
import time
from xml.dom import minidom
from WikiTextConverter import WikiTextConverter
class WikiPageCreator:
logger = logging.getLogger(__name__)
classesWithSubclasses = [
'gadgets.io',
'gadgets.skins',
'gadgets.views',
'opensocial.DataRequest',
'opensocial.Enum',
'opensocial.Environment',
'opensocial.IdSpec',
'opensocial.MediaItem',
'opensocial.NavigationParameters',
'opensocial.ResponseItem',
]
classesToRename = {
'Single Request Objects': 'osapi.Request',
'Batch Request Objects': 'osapi.BatchRequest',
'JavaScript Internationalization (i18n)': 'gadgets.i18n',
}
classesWithFields = [
'JavaScript Internationalization (i18n)',
'opensocial.CreateActivityPriority',
]
def __init__(self, osSpecFile, gadgetSpecFile):
# Create a DOM
self.osSpec = minidom.parse(osSpecFile)
self.gSpec = minidom.parse(gadgetSpecFile)
# Get the version number of the spec
self.specVersion = self.__getSpecVersion()
self.API_ALPHA_LIST = "\n\n{{ JsApiAlphaList_%s }}\n\n" % (self.specVersion)
self.ALPHA_LIST_HEADER = """
| '''OpenSocial %s''' |
""" % self.specVersion
self.ALPHA_LIST_FOOTER = '
'
# Instantiate an object to hold the wikified output
self.wiki = None
# Instantiate the converter
self.converter = WikiTextConverter(self.specVersion)
# Parses the spec version from the element in the section
# Returns the spec version. For example: (v0.9)
def __getSpecVersion(self):
front = self.osSpec.getElementsByTagName("front")[0]
title = front.getElementsByTagName("title")[0].firstChild.data
return "(%s)" % title[25:]
# Converts the spec to WikiMedia import/export format and prints the result
def run(self):
# Parse self.osSpec DOM (populates self.wiki)
self._parseOpenSocialSpec()
# Parse self.gSpec DOM (populates self.wiki)
self._parseGadgetSpec()
# Create the JsApiAlphaList page and the new API Reference homepage for this version
self._createApiReferencePages()
# Write the wiki DOM to stdout
print self.wiki.toxml(encoding="utf-8")
# Finds the part of the OpenSocial spec that contains the API reference and transforms it
# so it can be imported in to MediaWiki.
#
def _parseOpenSocialSpec(self):
# Create a document for the wikified API Reference
doc = minidom.parseString("""
""")
self.wiki = doc.firstChild
# Find
for node in self.osSpec.getElementsByTagName("section"):
title = node.getAttribute("title")
if (title == "API Class Reference"):
specApiRef = node
break
self._parseApiReference(specApiRef)
# Find
for node in self.osSpec.getElementsByTagName("section"):
title = node.getAttribute("title")
if (title == "Service Requests"):
osapiApiRef = node
break
self._parseApiReference(osapiApiRef)
# Find
for node in self.osSpec.getElementsByTagName("section"):
title = node.getAttribute("title")
if (title == "Service Objects"):
osapiApiRef = node
break
self._parseApiReference(osapiApiRef)
# Finds the part of the Gadget spec that contains the API reference and transforms it
# so it can be imported in to MediaWiki.
#
def _parseGadgetSpec(self):
# Find and parse it
for node in self.gSpec.getElementsByTagName("section"):
title = node.getAttribute("title")
if (title == "Core JavaScript API"):
coreApiRef = node
break
self._parseApiReference(coreApiRef)
# Find and parse it
for node in self.gSpec.getElementsByTagName("section"):
title = node.getAttribute("title")
if (title == "Highly Recommended Features"):
featuresApiRef = node
break
self._parseApiReference(featuresApiRef)
# Creates the main page for this version of the API Reference and the JsApiAlphaList template
# that gets inserted into the main page and each class page
def _createApiReferencePages(self):
title = "Template:JsApiAlphaList_%s" % self.specVersion
text = self.ALPHA_LIST_HEADER + ''
pages = self.wiki.getElementsByTagName('page')
linksPerColumn = (len(pages) / 4) + 1
count = 0
for node in pages:
count += 1
pageTitle = node.getElementsByTagName('title')[0].firstChild.data
linkText = pageTitle[:-len(self.specVersion)] # drop the spec version from the link text
text += '[[%s | %s]]\n\n' % (pageTitle, linkText)
if count % linksPerColumn == 0:
text += ' | \n'
text += " | " + self.ALPHA_LIST_FOOTER
alphaListPage = self._createPageElement(title, text)
self.wiki.appendChild(alphaListPage)
mainPageTitle = "JavaScript_API_Reference_%s" % self.specVersion
mainPageText = "{{ JsApiAlphaList_%s }}" % self.specVersion
mainPage = self._createPageElement(mainPageTitle, mainPageText)
self.wiki.appendChild(mainPage)
# Processes a part of the spec that contains API Reference
#
# @param specApiRef - a xml.dom.minidom.Node containing the API Reference section
def _parseApiReference(self, specApiRef):
for node in specApiRef.getElementsByTagName("section"):
if node.parentNode.isSameNode(specApiRef):
# Check for .Field classes and append them to the parent object's page
if node.getAttribute("title").endswith(".Field"):
pageTitle = node.getAttribute("title")[:-6] # drop the 6 chars in '.Field'
page = self._getPage("%s %s" % (pageTitle, self.specVersion))
self._addFields(page, node)
continue
# Check for classes with subclasses and append them to the existing parent object's page
found = False
for className in self.classesWithSubclasses:
if node.getAttribute("title").find("%s." % className) != -1:
self.logger.info("node title: %s className: %s" % (node.getAttribute("title"), className))
page = self._getPage("%s %s" % (className, self.specVersion))
self._addFields(page, node)
found = True
if found:
continue
# Otherwise create a new page for this class
if node.getAttribute("title") in self.classesToRename.keys():
title = "%s %s" % (self.classesToRename[node.getAttribute("title")], self.specVersion)
else:
title = "%s %s" % (node.getAttribute("title"), self.specVersion)
text = self.converter.convertClass(node)
text += self.API_ALPHA_LIST
newPage = self._createPageElement(title, text)
# Special case for gadgets i18n
if node.getAttribute("title") in self.classesWithFields:
self._addFields(newPage, node)
self.wiki.appendChild(newPage)
# Returns the wikified page corresponding to the given title
#
# param wiki A minidom.Document containing the wikified info
# param pageTitle A string with the title to search for
# returns A minidom.Node for the page with the given title
def _getPage(self, pageTitle):
for node in self.wiki.getElementsByTagName("page"):
nodeTitle = node.getElementsByTagName("title")[0].firstChild.data
if nodeTitle == pageTitle:
return node
# Creates a new element for a wiki page with the given title and populates it with the
# given text.
#
# param title a String containing the title of the page
# param text a String containing the wiki text for the page
# returns a minidom.Node representing a wiki page
def _createPageElement(self, title, text):
self.logger.info("Creating page for %s" % title)
# create the
page = minidom.Element("page")
# add the to the
titleNode = minidom.Element("title")
page.appendChild(titleNode)
titleText = minidom.Text()
titleText.data = title
titleNode.appendChild(titleText)
# add the to the
revision = minidom.Element("revision")
page.appendChild(revision)
# add a to the
timestamp = minidom.Element("timestamp")
timestampText = minidom.Text()
timestampText.data = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
timestamp.appendChild(timestampText)
revision.appendChild(timestamp)
# add the to the
textNode = minidom.Element("text")
textNode.setAttribute("xml:space", "preserve")
textText = minidom.Text()
textText.data = text
textNode.appendChild(textText)
revision.appendChild(textNode)
return page
# Appends the fields from the spec to the given wikified page
#
# param page A minidom.Node with wikified info for an OpenSocial class
# param specFields A minidom.Node with fields in spec format
def _addFields(self, page, specFields):
pageTitle = page.getElementsByTagName("title")[0]
self.logger.info("Adding fields to page for %s" % pageTitle.firstChild.data)
text = page.getElementsByTagName("text")[0].firstChild
# Remove the Alphalist after the class
text.data = text.data[:-len(self.API_ALPHA_LIST)]
# Add the wiki text for the fields
text.data = text.data + self.converter.convertFields(specFields)
# Re-add the Alphalist after the fields
text.data += self.API_ALPHA_LIST