blob: e2f1ee28e0bcdd434d949802611ae41423eeb0bd [file] [log] [blame]
/* Bradley Childs (childsb@us.ibm.com)
*
* This partitioner is an 'intercepter' for a bigger, stronger partitioner.
*
*/
package org.eclipse.wst.jsdt.web.core.internal.text;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.wst.jsdt.web.core.internal.java.JsDataTypes;
import org.eclipse.wst.jsdt.web.core.internal.java.NodeHelper;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredTextPartitioner;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.sse.core.internal.text.rules.IStructuredTypedRegion;
import org.eclipse.wst.sse.core.internal.text.rules.SimpleStructuredTypedRegion;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
public class StructuredTextPartitionerScripHelper implements
IStructuredTextPartitioner {
private IDocument fInternalDocument;
private IStructuredTextPartitioner fMasterPartitioner;
private static Hashtable newPartitionType = new Hashtable();
private static Hashtable contentTypeMap = new Hashtable();
private String[] subPartitionType;
public StructuredTextPartitionerScripHelper(
IStructuredTextPartitioner masterPartitioner,
String[] subPartitionType, String newPartitionType) {
setMasterPartitioner(masterPartitioner);
this.subPartitionType = subPartitionType;
StructuredTextPartitionerScripHelper.newPartitionType.put(
subPartitionType, newPartitionType);
}
public void setMasterPartitioner(
IStructuredTextPartitioner embeddedPartitioner) {
/*
* manage connected state of embedded partitioner
*/
if (fMasterPartitioner != null && fInternalDocument != null) {
fMasterPartitioner.disconnect();
contentTypeMap.remove(fMasterPartitioner);
}
this.fMasterPartitioner = embeddedPartitioner;
if (fMasterPartitioner != null && fInternalDocument != null) {
fMasterPartitioner.connect(fInternalDocument);
}
if (fMasterPartitioner != null) {
try {
Class[] parameterTypes = new Class[] {};
Class c = fMasterPartitioner.getClass();
Object[] arguments = new Object[] {};
Method getConfiguredContentTypes = c.getMethod(
"getConfiguredContentTypes", parameterTypes);
String[] additionalContentTypes = (String[]) getConfiguredContentTypes
.invoke(fMasterPartitioner, arguments);
contentTypeMap.put(fMasterPartitioner, additionalContentTypes);
} catch (Exception e) {
}
}
}
public static String[] getConfiguredContentTypes(
IStructuredTextPartitioner partitioner) {
return (String[]) contentTypeMap.get(partitioner);
}
public static String[] getConfiguredContentTypes() {
/*
* return every content type support (may be MANY if used in multiple
* partition types.. This includes every static registerd master
* partitioner, and all of the new content types this classes brings
* along.
*/
Enumeration keys = contentTypeMap.keys();
Vector contentTypes = new Vector();
while (keys.hasMoreElements()) {
String[] addContentTypes = (String[]) contentTypeMap.get(keys
.nextElement());
for (int i = 0; i < addContentTypes.length; i++) {
if (addContentTypes[i] != null
&& !addContentTypes[i].equals("")) {
contentTypes.add(addContentTypes[i]);
}
}
}
keys = newPartitionType.keys();
while (keys.hasMoreElements()) {
String addContentTypes = (String) newPartitionType.get(keys
.nextElement());
if (addContentTypes != null && !addContentTypes.equals("")) {
contentTypes.add(addContentTypes);
}
}
for (int i = 0; i < contentTypes.size(); i++) {
System.out.println(contentTypes.elementAt(i));
}
return (String[]) (contentTypes.toArray(new String[0]));
}
public StructuredTextPartitionerScripHelper() {
/*
* Should read extension points here and dynamically set the 'master'
* partitioner but its hard coded to the JSP partitioner ATM.
*/
this(new StructuredTextPartitionerForJSP(),
JsDataTypes.TAKEOVER_PARTITION_TYPES,
JsDataTypes.NEW_PARTITION_TYPE);
}
public void setEmbeddedPartitioner(
IStructuredTextPartitioner embeddedPartitioner) {
/* Required from the JSP partitioner............... SHOULD REMOVE! */
try {
Class[] parameterTypes = new Class[] { IStructuredTextPartitioner.class };
Class c = fMasterPartitioner.getClass();
Object[] arguments = new Object[] { embeddedPartitioner };
Method setLanguageMethod = c.getMethod("setEmbeddedPartitioner",
parameterTypes);
setLanguageMethod.invoke(fMasterPartitioner, arguments);
} catch (Exception e) {
// oops wrong class type
}
}
public void setLanguage(String language) {
try {
Class[] parameterTypes = new Class[] { String.class };
Class c = fMasterPartitioner.getClass();
Object[] arguments = new Object[] { language };
Method setLanguageMethod = c.getMethod("setLanguage",
parameterTypes);
setLanguageMethod.invoke(fMasterPartitioner, arguments);
} catch (Exception e) {
// oops wrong class type
}
}
public void connect(IDocument document) {
this.fInternalDocument = document;
if (fMasterPartitioner != null) {
fMasterPartitioner.connect(document);
}
}
public IStructuredTypedRegion createPartition(int offset, int length,
String partitionType) {
// String parType =
// isSubPartitionType(partitionType)?(String)newPartitionType.get(subPartitionType):partitionType;
System.out.println("Called create partition on type " + partitionType);
return fMasterPartitioner
.createPartition(offset, length, partitionType);
}
public String getDefaultPartitionType() {
String partitionType = fMasterPartitioner.getDefaultPartitionType();
return isSubPartitionType(partitionType) ? (String) newPartitionType
.get(subPartitionType) : partitionType;
}
public String getPartitionType(ITextRegion region, int offset) {
String partitionType = fMasterPartitioner.getPartitionType(region,
offset);
System.out.println("Region Par Type:" + partitionType
+ "------------------------------------------");
System.out.println(fInternalDocument.get().substring(region.getStart(),
region.getTextEnd()));
System.out
.println("/Region:--------------------------------------------");
return isSubPartitionType(partitionType) ? (String) newPartitionType
.get(subPartitionType) : partitionType;
}
public String getPartitionTypeBetween(
IStructuredDocumentRegion previousNode,
IStructuredDocumentRegion nextNode) {
System.out.println("getPartitoinTypeBetween");
String partitionType = fMasterPartitioner.getPartitionTypeBetween(
previousNode, nextNode);
if (isSubPartitionType(partitionType)) {
return (String) newPartitionType.get(subPartitionType);
} else {
return partitionType;
}
}
public ITypedRegion[] computePartitioning(int offset, int length) {
//
// /* Look for EVENTs and label them SCRIPT partitions */
//
// System.out.println("Compute Partitions--------");
// System.out.println(fInternalDocument.get().substring(offset,offset+length));
// Vector typedRegions = new Vector();
//
// if(fInternalDocument instanceof IStructuredDocument){
// IStructuredDocument structDoc =
// (IStructuredDocument)(fInternalDocument);
// IStructuredDocumentRegion[] regions =
// structDoc.getStructuredDocumentRegions(offset, length);
//
// if(regions==null) return new ITypedRegion[]{};
// NodeHelper nh;
//
//
// for(int i = 0;i<regions.length;i++){
// if(regions[i].getType()==DOMRegionContext.XML_TAG_NAME && (nh = new
// NodeHelper(regions[i])).containsAttribute(JsDataTypes.HTMLATREVENTS)){
// // Found an event tag!
// ITextRegionList t = regions[i].getRegions();
// ITextRegion r;
// Iterator regionIterator = t.iterator();
// String tagAttrname = new String();
// while(regionIterator.hasNext() ){
// r = (ITextRegion)regionIterator.next();
//
// if(r.getType()== DOMRegionContext.XML_TAG_ATTRIBUTE_NAME){
// tagAttrname = regions[i].getText().substring(r.getStart() ,
// r.getTextEnd()).trim();
//
// }else if(r.getType()==DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE &&
// nh.isInArray(JsDataTypes.HTMLATREVENTS, tagAttrname)){
// System.out.println("Found script event type:--------");
// System.out.println(regions[i].getText().substring(r.getStart() ,
// r.getTextEnd()));
// System.out.println("/Found script event type:--------");
//
// boolean isQuoted =
// nh.isQuoted(regions[i].getText().substring(r.getStart() ,
// r.getTextEnd()));
//
// int quoteOffset = isQuoted?1:0;
//
// typedRegions.add(new
// SimpleStructuredTypedRegion(r.getStart()+quoteOffset,
// r.getLength() - quoteOffset*2,
// (String)newPartitionType.get(subPartitionType)));
// createPartition(r.getStart()+quoteOffset,
// r.getLength()- quoteOffset*2,
// (String)newPartitionType.get(subPartitionType));
//
// createPartition( r.getStart()+quoteOffset,
// r.getLength()- quoteOffset*2,
// (String)newPartitionType.get(subPartitionType));
// tagAttrname = new String();
//
// /* Add two arbitrary 1 char positions if quoted */
//
// if(isQuoted){
//
// typedRegions.addAll(Arrays.asList(fMasterPartitioner.computePartitioning(r.getStart(),1)));
// typedRegions.addAll(Arrays.asList(fMasterPartitioner.computePartitioning(r.getTextEnd(),1)));
//
//
// }
//
//
// }else{
//
// typedRegions.addAll(Arrays.asList(fMasterPartitioner.computePartitioning(r.getStart(),r.getLength())));
// }
//
//
// }
//
// }else{
// // not a name tag so compute its partition
// /*
// typedRegions.add(new
// SimpleStructuredTypedRegion(regions[i].getStart(),
// regions[i].getLength(),
// (String)newPartitionType.get(subPartitionType)));
// createPartition(regions[i].getStart(),
// regions[i].getLength(),
// (String)newPartitionType.get(subPartitionType));
//
//
// */
//
// // Let somebody else compute this partition type
// typedRegions.addAll(Arrays.asList(fMasterPartitioner.computePartitioning(regions[i].getStart(),regions[i].getLength())));
// }
//
// } // End for loop itterating over all sub regions in this region.
//
// }
//
// System.out.println("/Compute Partitions--------");
return fMasterPartitioner.computePartitioning(offset, length);
// return (ITypedRegion[])typedRegions.toArray(new ITypedRegion[]{});
}
public void disconnect() {
fMasterPartitioner.disconnect();
}
public void documentAboutToBeChanged(DocumentEvent event) {
fMasterPartitioner.documentAboutToBeChanged(event);
}
public boolean documentChanged(DocumentEvent event) {
return fMasterPartitioner.documentChanged(event);
}
public String getContentType(int offset) {
System.out.println("Queried for content type");
if (!(fInternalDocument instanceof IStructuredDocument)) {
return fMasterPartitioner.getContentType(offset);
}
IStructuredDocument structDoc = (IStructuredDocument) (fInternalDocument);
IStructuredDocumentRegion structuredDocRegion = structDoc
.getRegionAtCharacterOffset(offset);
ITextRegion currentRegion = structuredDocRegion
.getRegionAtCharacterOffset(offset);
/* If its not an XML_TAG_ATTRIBUTE inspect no further */
if (currentRegion.getType() != DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
return fMasterPartitioner.getContentType(offset);
}
/* make sure we're not at a quoted character */
if (structDoc.get().charAt(offset) == '\''
| structDoc.get().charAt(offset) == '"') {
return fMasterPartitioner.getContentType(offset);
}
/*
* If we've fallen through to here, then we're in a
* XML_TAG_ATTRIBUTE_VALUE need to check if this event type tag
*/
ITextRegionList regionList = structuredDocRegion.getRegions();
int currentIndex = regionList.indexOf(currentRegion);
/*
* We determinate attrib name 2 previous regions: Node
* Type:XML_TAG_ATTRIBUTE_NAME Node Type:XML_TAG_ATTRIBUTE_EQUALS Node
* Type:XML_TAG_ATTRIBUTE_VALUE
*/
if ((currentIndex - 2) < 0) {
return fMasterPartitioner.getContentType(offset);
}
ITextRegion tagAttrNameRegion = regionList.get(currentIndex - 2);
String tagAttrName = structuredDocRegion.getText().substring(
tagAttrNameRegion.getStart(), tagAttrNameRegion.getTextEnd())
.trim();
if (NodeHelper.isInArray(JsDataTypes.HTMLATREVENTS, tagAttrName)) {
System.out.println("returning JS content type");
return (String) newPartitionType.get(subPartitionType);
}
return fMasterPartitioner.getContentType(offset);
}
public String[] getLegalContentTypes() {
return fMasterPartitioner.getLegalContentTypes();
}
public ITypedRegion getPartition(int offset) {
if (getContentType(offset) != (String) newPartitionType
.get(subPartitionType)) {
return fMasterPartitioner.getPartition(offset);
}
if (!(fInternalDocument instanceof IStructuredDocument)) {
return fMasterPartitioner.getPartition(offset);
}
IStructuredDocument structDoc = (IStructuredDocument) (fInternalDocument);
IStructuredDocumentRegion structuredDocRegion = structDoc
.getRegionAtCharacterOffset(offset);
ITextRegion currentRegion = structuredDocRegion
.getRegionAtCharacterOffset(offset);
boolean isAttrQuoted = NodeHelper.isQuoted(structuredDocRegion
.getText().substring(currentRegion.getStart(),
currentRegion.getTextEnd()));
int quoteOffset = isAttrQuoted ? 1 : 0;
ITypedRegion jsTypedRegion = new SimpleStructuredTypedRegion(
currentRegion.getStart() + quoteOffset, currentRegion
.getLength()
- quoteOffset * 2, (String) newPartitionType
.get(subPartitionType));
createPartition(jsTypedRegion.getOffset(), jsTypedRegion.getLength(),
jsTypedRegion.getType());
return jsTypedRegion;
}
public IDocumentPartitioner newInstance() {
return new StructuredTextPartitionerForJSP();
}
private boolean isSubPartitionType(String type) {
return NodeHelper.isInArray(subPartitionType, type);
}
@Override
public void finalize() {
if (newPartitionType != null) {
newPartitionType.remove(subPartitionType);
}
if (contentTypeMap != null) {
contentTypeMap.remove(fMasterPartitioner);
}
}
}