All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.disney.groovity.tags.Write Maven / Gradle / Ivy

There is a newer version: 2.1.0-beta.1
Show newest version
/*******************************************************************************
 * © 2018 Disney | ABC Television Group
 *
 * Licensed under the Apache License, Version 2.0 (the "Apache License")
 * with the following modification; you may not use this file except in
 * compliance with the Apache License and the following modification to it:
 * Section 6. Trademarks. is deleted and replaced with:
 *
 * 6. Trademarks. This License does not grant permission to use the trade
 *     names, trademarks, service marks, or product names of the Licensor
 *     and its affiliates, except as required to comply with Section 4(c) of
 *     the License and to reproduce the content of the NOTICE file.
 *
 * You may obtain a copy of the Apache License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the Apache License with the above modification is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the Apache License for the specific
 * language governing permissions and limitations under the Apache License.
 *******************************************************************************/
package com.disney.groovity.tags;

import java.io.CharArrayWriter;
import java.io.Writer;
import java.util.Collection;
import java.util.Formatter;
import java.util.Map;

import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;

import com.disney.groovity.GroovityConstants;
import com.disney.groovity.Taggable;
import com.disney.groovity.doc.Attr;
import com.disney.groovity.doc.Tag;
import com.disney.groovity.model.ModelFilter;
import com.disney.groovity.model.ModelWalker;
import com.disney.groovity.model.ModelJsonWriter;
import com.disney.groovity.model.ModelTemplateWriter;
import com.disney.groovity.model.ModelXmlWriter;
import com.disney.groovity.util.HtmlEscapingWriter;
import com.disney.groovity.util.JsonEscapingWriter;
import com.disney.groovity.util.XmlEscapingWriter;

import groovy.lang.Closure;
import groovy.lang.GroovySystem;
import groovy.lang.MetaClass;
import groovy.lang.MetaProperty;
import groovy.lang.Writable;

/**
 * Serializes value to out in json or string format
 * 

* write(

    *
  • value: * The object or collection to be written,
  • *
  • var: * The variable name to store the destination of the write operation, as specified by 'to',
  • *
  • format: * 'xml' or 'json' for writing structured data (json is default), '~' to use templates found in the value or injected by ModelFilters, or a java String Format to serialize the value, or body can be used to generate raw characters,
  • *
  • pretty: * pretty print json or xml,
  • *
  • null: * value to display for null, defaults to empty string,
  • *
  • escape: * escape the output as one of (xml|html|json),
  • *
  • to: * a writer to print the output to, defaults to binding out, or can specify String.class or empty string to write to a string,
  • *
  • filter: * A ModelFilter or collection of ModelFilter objects to be used to transform the value during json or xml serialization,
  • *
  • root: * custom root element name for XML output
  • *
  • namespaces: * custom mapping of namespace prefixes to namespace URIs
  • *
{ *
// code that writes output that will be printed if no value is specified
* }); * *

returns the writer specified as to, or a String if to is empty string * *

Sample *

 *	<~ <g:write value="${['a','b','c']}" pretty="true" escape="json" /> ~>
 *	
* * @author Alex Vigdor */ @Tag( info="Serializes value to out in json or string format", body="code that writes output that will be printed if no value is specified", sample="<~ ~>", returns="the writer specified as to, or a String if to is empty string", attrs={ @Attr(name=GroovityConstants.VALUE,required=false,info="The object or collection to be written"), @Attr(name=GroovityConstants.VAR,required=false,info="The variable name to store the destination of the write operation, as specified by 'to'"), @Attr(name="format",required=false,info="'xml' or 'json' for writing structured data (json is default), '~' to use templates found in the value or injected by ModelFilters, or a java String Format to serialize the value, or body can be used to generate raw characters"), @Attr(name="pretty",required=false,info="pretty print json or xml"), @Attr(name="null",required=false,info="value to display for null, defaults to empty string"), @Attr(name="escape",required=false,info="escape the output as one of (xml|html|json)"), @Attr(name="to",required=false,info="a writer to print the output to, defaults to binding out, or can specify String.class or empty string to write to a string"), @Attr(name="filter",required=false,info="A ModelFilter or collection of ModelFilter objects to be used to transform the value during json or xml serialization"), @Attr(name="root",required=false,info="custom root element name for XML output"), @Attr(name="namespaces",required=false,info="custom mapping of namespace prefixes to namespace URIs") } ) public class Write implements Taggable{ @SuppressWarnings({ "rawtypes", "resource" }) public Object tag(Map attributes, Closure body) throws Exception { boolean valueDeclared = attributes.containsKey(VALUE); Object value = null; if(valueDeclared){ value = resolve(attributes,VALUE); if(value==null){ value = resolve(attributes,"null"); } } Object format = resolve(attributes,"format"); Object escape = resolve(attributes,"escape"); Object pretty = resolve(attributes,"pretty"); if(pretty!=null && !(pretty instanceof Boolean)){ pretty = Boolean.valueOf(pretty.toString()); } Object to = resolve(attributes,"to"); boolean returnTo = true; if(to==null){ returnTo = false; //fall back on body out to=get(body,OUT); } if(to==null){ throw new IllegalArgumentException("write tag requires valid Writer or String.class for 'to'"); } Object filter = resolve(attributes,"filter"); Writer writer; boolean returnString = false; if(to instanceof Writer) { writer = (Writer) to; } else if(to.equals(String.class) || to instanceof CharSequence) { writer = new CharArrayWriter(); returnString = true; } else { throw new IllegalArgumentException("write tag requires valid Writer or String.class for 'to', unrecognized option "+to); } if(escape!=null){ String esc = escape.toString(); if(esc.equalsIgnoreCase("xml")){ writer = new XmlEscapingWriter(writer); } else if(esc.equalsIgnoreCase("json")){ writer = new JsonEscapingWriter(writer); } else if(esc.equalsIgnoreCase("html")){ writer = new HtmlEscapingWriter(writer); } else{ throw new IllegalArgumentException("Unrecognized escape value "+esc+", try xml or json"); } } if(value == null){ Object oldOut = get(body,OUT); bind(body,OUT, writer); try { value = body.call(); } finally { bind(body,OUT, oldOut); } } if(value!=null){ if(format!=null && !"json".equals(format) && !"xml".equals(format) && !"~".equals(format)){ //we don't want to close the formatter because it's not our job to close the writer Formatter formatter = new Formatter(writer); if(value instanceof Collection){ formatter.format(format.toString(), ((Collection)value).toArray()); } else{ formatter.format(format.toString(), value); } } else{ if(value instanceof CharSequence){ writer.append((CharSequence)value); } else if((filter==null) && (value instanceof Writable) && (value!=body.getOwner())){ ((Writable)value).writeTo(writer); } else{ ModelWalker mw; if(format==null) { Object response = get(body,"response"); if(response!=null) { MetaClass mc = GroovySystem.getMetaClassRegistry().getMetaClass(response.getClass()); MetaProperty mp = mc.hasProperty(response, "contentType"); if(mp!=null) { String ct = (String) mp.getProperty(response); if(ct!=null && ct.contains("xml")) { format="xml"; } } } } if("xml".equals(format)) { if(pretty!=null && ((Boolean)pretty).booleanValue()){ mw = new ModelXmlWriter(writer,"\t"); //prevent secondary pretty, just write it pretty up front! pretty = Boolean.FALSE; } else{ mw = new ModelXmlWriter(writer); } String root = resolve(attributes,"root",String.class); if(root!=null) { ((ModelXmlWriter)mw).setRootElementName(root); } @SuppressWarnings("unchecked") Map prefixes = resolve(attributes,"namespaces",Map.class); if(prefixes!=null) { ((ModelXmlWriter)mw).setNamespacePrefixes(prefixes); } } else if("~".equals(format)) { mw = new ModelTemplateWriter(writer); } else { if(pretty!=null && ((Boolean)pretty).booleanValue()){ mw = new ModelJsonWriter(writer,"\t"); //prevent secondary pretty, just write it pretty up front! pretty = Boolean.FALSE; } else{ mw = new ModelJsonWriter(writer); } } if(filter!=null) { ModelFilter[] mfa = null; if(filter instanceof Collection) { Collection src = (Collection) filter; mfa = new ModelFilter[src.size()]; int pos = 0; for(Object mf: src) { mfa[pos++] = (ModelFilter) DefaultTypeTransformation.castToType(mf,ModelFilter.class); } } else if(filter.getClass().isArray() && filter.getClass().getComponentType().equals(ModelFilter.class)) { mfa = (ModelFilter[]) filter; } else if(filter instanceof ModelFilter) { mfa = new ModelFilter[] {(ModelFilter)filter}; } else { mfa = new ModelFilter[] { (ModelFilter) DefaultTypeTransformation.castToType(filter,ModelFilter.class)}; } mw.setFilters(mfa); } mw.visit(value); } } } if(!returnTo) { return null; } Object rval = returnString ? writer.toString() : writer; if(attributes.get(VAR) != null) { bind(body,attributes.get(VAR).toString(),rval); } return rval; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy