T4, how to use EnvDTE get static class - t4

how to use EnvDTE get static class
<## template debug="false" hostspecific="true" language="C#" #>
<## assembly name="System.Core" #>
<## assembly name="EnvDTE" #>
<## import namespace="System.Linq" #>
<## import namespace="System.Text" #>
<## import namespace="System.Collections.Generic" #>
<## import namespace="EnvDTE" #>
<## output extension=".txt" #>
<#
IServiceProvider hostServiceProvider = Host as IServiceProvider;
EnvDTE.DTE dte = hostServiceProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
EnvDTE.ProjectItem containingProjectItem = dte.Solution.FindProjectItem(Host.TemplateFile);
Project project = containingProjectItem.ContainingProject;
var codes= project.CodeModel.CodeElements;
foreach (CodeElement code in codes) {
if (code.Name=="MS") continue;
if (code.Name=="System") continue;
if (code.Name=="Microsoft") continue;
if (code.Name.StartsWith("EnvDTE")) continue;
try
{
foreach (CodeElement item in ((CodeNamespace)code).Members) {
if (item.Kind== vsCMElement.vsCMElementClass) {
CodeClass cc = (CodeClass)item;
#>
<#=cc.Name #>
<#
}
}
} catch {}
} #>
this is T4 codes;
It can output the class name,
But it can not determine whether the class is static.
I want to output static class name.

Add references:
<## assembly name="EnvDTE80" #>
<## import namespace="EnvDTE80" #>
Use CodeClass2 interface, that has IsShared property

Related

Why HSQL not support count function in a spring batch project

I am new to SpringBatch And HSQL, I simple create an application. I
want to select all the rows from the table ,So I write custom query By
using EntityManager but when I Use COUNT(*),and pass Star symbol
inside the count function it show me an error Like this
<expression>, ALL, DISTINCT or identifier expected, got '*'
How to I use * symbol inside the Count function in Hsql
Here is the my query details
JobCompleteNotificationListner.kt
package com.nilmani.privatecricketleague.data
import com.nilmani.privatecricketleague.model.Team
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.batch.core.BatchStatus
import org.springframework.batch.core.JobExecution
import org.springframework.batch.core.listener.JobExecutionListenerSupport
import java.util.*
import javax.persistence.EntityManager
import javax.persistence.Transient
import kotlin.collections.HashMap
class JobCompleteNotificationListner : JobExecutionListenerSupport {
val log:Logger = LoggerFactory.getLogger(JobCompleteNotificationListner::class.java)
val em:EntityManager
constructor(em:EntityManager){this.em= em}
#Transient
override fun afterJob(jobExcution:JobExecution){
if (jobExcution.status == BatchStatus.COMPLETED){
log.info("Job finished Time to verify the result")
val teamData:Map<String,Team> = HashMap()
em.createQuery("SELECT m.team1 , COUNT(*) FROM match m GROUP BY m.team1",Objects::class.java)
}
}
}
I get error at this below line
em.createQuery("SELECT m.team1 , COUNT(*) FROM match m GROUP BY m.team1",Objects::class.java)

Django-filter BooleanFilter with rest framework

I would like to set a field by using BooleanFilter that filters where quantity_remaining > 0.
This is what I have written down so far:
in_stock = filters.BooleanFilter(field_name="quantity_remaining",lookup_expr="gt")
You can use NumberFilter And set lookup_expr as gt like this.
from django_filters.rest_framework import BaseInFilter, NumberFilter
import django_filters.rest_framework
import django_filters.filters
class NumberInFilter(BaseInFilter, NumberFilter):
pass
class FilterClass(django_filters.rest_framework.FilterSet):
in_stock = NumberInFilter(field_name="quantity_remaining", lookup_expr="gt")
class StockClass(ListAPIView):
filterset_class = FilterClass

How could let MyBatis Generator overwriting the already generated *Mapper.xml?

Like title, when i execute the mybatis-generator, i want to overwriting the already generated *Mapper.xml all, not merge!
but i try many config way, it doesn't implement correct.
and everytime is generator the more once the xml content.
like this:
<resultMap id="BaseResultMap" type="com.test.entity.GoodsEntity"> ...
<resultMap id="BaseResultMap" type="com.test.entity.GoodsEntity"> ...
<resultMap id="BaseResultMap" type="com.test.entity.GoodsEntity"> ...
in the properties, i had add this line:
<mybatis.generator.overwrite>true</mybatis.generator.overwrite>
and in the build > plugin, i add below lines:
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
<configurationFile>${mybatis.generator.configurationFile}</configurationFile>
</configuration>
<executions>
<execution>
<id>Generate MyBatis Artifacts</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>ob-maven-plugin-mybatis-generator</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</plugin>
in the mybatis-generator.xml, i try overwrite config yet.
all config it doesn't work goo.
How could I modify the configuration?
MyBatis generator will always merge XML files if it finds a match. There is currently no option to turn that off.
You can use plugin <plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin" /> in Mybatis Generator 1.3.7 to overwrite xml.
See http://www.mybatis.org/generator/reference/plugins.html
This plugin will disable the XML merge function for generated mapper XML files. This will cause the generator to respect the overwrite flag for XML files in the same way it does for Java files - if overwrite is true, then an existing file will be overwritten, else a new file will be written with a unique name.
This plugin can be helpful if you disable all comments.
Setting <property name="suppressAllComments" value="true" /> in Mybatis Generator configuration file can cause this problem. Mybatis Generator uses comments flag to decide whether to merge XML.
If you disable all comments, you might find the UnmergeableXmlMappersPlugin useful. It will cause the generator to respect the overwrite flag for XML files.
See http://www.mybatis.org/generator/configreference/commentGenerator.html
I was able to get around this by creating a plugin and adding it to the mybatis-generator-config.xml file. Note, of course, that this solution will cause the Mapper.xml files to always be overwritten regardless of whether or not the -overwrite flag is specified.
mybatis-generator-config.xml:
<generatorConfiguration>
...
<context id="myContextId">
<plugin type="com.mydomain.DeleteExistingSqlMapsPlugin"></plugin>
...
</context>
</generatorConfiguration>
DeleteExistingSqlMapsPlugin.java:
...
public class DeleteExistingSqlMapsPlugin extends PluginAdapter {
#Override
public boolean validate(List<String> warnings) {
return true;
}
#Override
public boolean sqlMapGenerated(GeneratedXmlFile sqlMap,
IntrospectedTable introspectedTable)
{
String sqlMapPath = sqlMap.getTargetProject() + File.separator
+ sqlMap.getTargetPackage().replaceAll("\\.", File.separator)
+ File.separator + sqlMap.getFileName();
File sqlMapFile = new File(sqlMapPath);
sqlMapFile.delete();
return true;
}
}
This works because sqlMapGenerated() is called after a Mapper.xml file is created in memory but before it is written to disk.
I encountered the same problem today.To solve this problem, just need to change the version of mybatis-generator-maven-plugin。
<mybatis-generator-maven-plugin.version>1.3.4-SNAPSHOT</mybatis-generator-maven-plugin.version>
I write a plugin to merge xml mapper file.
And modifiy mybatis-generator-core to combine java and xml.
This can keep your xml and java file 's modification not override.
https://github.com/zwxbest/mybatis-generator-plugin
Usage:
<generatorConfiguration>
...
<context id="myContextId">
<plugin type="com.mydomain.CombineXmlPlugin"></plugin>
...
</context>
</generatorConfiguration>
Plugin Code:
package com.haitian.plugins;
import org.mybatis.generator.api.GeneratedXmlFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.ShellCallback;
import org.mybatis.generator.api.dom.xml.Element;
import org.mybatis.generator.internal.DefaultShellCallback;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.FileInputStream;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* User:zhangweixiao
* Description:
* old nodes is your existing xml file's first level nodes,like <insert><resultMap>
* new nodes is mybatis-generator generate for you to combine
* This compare the first level node's name and "id" attribute of new nodes and old nodes
* if the two equal,then new node will not generate
* so this can make you modification in old nodes not override.
* if you want to regenrate old node,delete it,it will generate new.
*/
public class CombineXmlPlugin extends PluginAdapter {
//shellCallback use TargetProject and TargetPackage to get targetFile
ShellCallback shellCallback = new DefaultShellCallback(false);
//save new nodes
org.mybatis.generator.api.dom.xml.Document document;
#Override
public boolean validate(List<String> warnings) {
return true;
}
/**
* assing document variable to get new nodes
* #param document
* #param introspectedTable
* #return
*/
#Override
public boolean sqlMapDocumentGenerated(org.mybatis.generator.api.dom.xml.Document document,
IntrospectedTable introspectedTable) {
this.document = document;
return true;
}
//new nodes is generated,but not write on disk,we just need to filter.
#Override
public boolean sqlMapGenerated(GeneratedXmlFile sqlMap,
IntrospectedTable introspectedTable) {
try {
//get old nodes
File directory = shellCallback.getDirectory(sqlMap.getTargetProject(), sqlMap.getTargetPackage());
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
DocumentBuilder db = dbf.newDocumentBuilder();
File xmlFile = new File(directory, sqlMap.getFileName());
if (directory.exists() == false || xmlFile.exists() == false)
return true;
Document doc = db.parse(new FileInputStream(xmlFile));
org.w3c.dom.Element rootElement = doc.getDocumentElement();
NodeList list = rootElement.getChildNodes();
//get new nodes
List<Element> elements = document.getRootElement().getElements();
//get nodeName and the value of id attribute use regex
Pattern p = Pattern.compile("<(\\w+)\\s+id=\"(\\w+)\"");
boolean findSameNode = false;
// traverse new nodes to compare old nodes to filter
for (Iterator<Element> elementIt = elements.iterator(); elementIt.hasNext(); ) {
findSameNode = false;
String newNodeName = "";
String NewIdValue = "";
Element element = elementIt.next();
Matcher m = p.matcher(element.getFormattedContent(0));
if (m.find()) {
//get nodeName and the value of id attribute
newNodeName = m.group(1);
NewIdValue = m.group(2);
}
//if the nodeName of newNode and oldNode are equal
//and the id attribute of newNode and oldNode are equal
//then filter newNode
for (int i = 0; i < list.getLength(); i++) {
Node node = list.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
if (newNodeName.equals(node.getNodeName())) {
NamedNodeMap attr = node.getAttributes();
for (int j = 0; j < attr.getLength(); j++) {
Node attrNode = attr.item(j);
if (attrNode.getNodeName().equals("id") && attrNode.getNodeValue().equals(NewIdValue)) {
//filter new node,just delete it ,and it will not generate
elementIt.remove();
findSameNode = true;
break;
}
}
if (findSameNode == true)
break;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
}
you add "batchInsert",and delte insertSelective,and modify other node.
then regenerate xml mapper file,only insertSelective will be generated,others will not be override.

T4 trouble compiling transformation

I can't figure this one out. Why doesn't T4 locate the IEnumerable type? I'm using Visual Studio 2010. And I just hope someone knows why?
<## template debug="true" hostspecific="false" language="C#" #>
<## assembly name="System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" #>
<## import namespace="System" #>
<## import namespace="System.Data" #>
<## import namespace="System.Data.SqlClient" #>
<## output extension=".cs" #>
public static class Tables
{
<#
var q = #"
SELECT
tbl.name 'table',
col.name 'column'
FROM
sys.tables tbl
INNER JOIN
sys.columns col ON col.object_id = tbl.object_id
";
// var source = Execute(q);
#>
}
<#+
static IEnumerable Execute(string cmdText)
{
using (var conn = new SqlConnection(#"Data Source=.\SQLEXPRESS;Initial Catalog=t4build;Integrated Security=True;"))
{
conn.Open();
var cmd = new SqlCommand(cmdText, conn);
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
}
}
}
}
#>
Error 2 Compiling transformation: The type or namespace name 'IEnumerable' could not be found (are you missing a using directive or an assembly reference?) c:\Projects\T4BuildApp\T4BuildApp\TextTemplate1.tt 26 9
I would also recommend to referece #assembly name="System.Core" and #import "System.Linq" so you get more power when doing something with IEnumerable
Probably because IEnumerable is in System.Collections.

How do I use templates inside a T4 ClassBlock method?

I'm starting to investigate T4 for Code Generation.
I get that you have a basic template in which you can embed little chunks of c#/vb which can perform clever stuff...
<## template language="VB" debug="True" hostspecific="True" #>
<## output extension=".vb" debug="True" hostspecific="True" #>
Imports System
<#For Each Table as String in New String(0 {"Table1","Table2"}#>
Public Class <#=Table#>DA
Public Sub New
<#= WriteConstructorBody() #>
End Sub
End Class
<#Next#>
<#+
Public Function WriteConstructorBody() as String
return "' Some comment"
End function
#>
This is great.. However I would like to be able to write my main block thus...
<## template language="VB" debug="True" hostspecific="True" #>
<## output extension=".vb" debug="True" hostspecific="True" #>
Imports System
<#
For Each BaseTableName as String in New String(){"Table1","Table2"}
WriteRecDataInterface(BaseTableName)
WriteRecDataClass(BaseTableName)
WriteDAInterface(BaseTableName)
WriteDAClass(BaseTableName)
Next
#>
Then I would like to be able to have the WriteX methods exist in a Class Block but themselves be writable using code by example ie escaped Code blocks.
How can I achieve this?
You can write.....
<## template language="VB" debug="True" hostspecific="True" #>
<## output extension=".vb" debug="True" hostspecific="True" #>
Imports System
<#
For Each BaseTableName as String in New String(){"Table1","Table2"}
WriteRecDataInterface(BaseTableName)
' WriteRecDataClass(BaseTableName)
' WriteDAInterface(BaseTableName)
' WriteDAClass(BaseTableName)
Next
#>
<#+ Public Sub WriteRecDataInterface(BaseTableName as String)#>
Some Templated unescaped code might go here
<#+ For SomeLoopVar as Integer = 1 to 10 #>
Some Templated unescaped code might go here
<#+ Next #>
Some Templated unescaped code might go here
<#+ End Sub #>
'...
'...
' Other Subs left out for brevity
'...
It seems that you can mix static output with template code in Class Blocks. Here is an example with C#:
<## template language="C#" #>
<# HelloWorld(); #>
<#+
private string _field = "classy";
private void HelloWorld()
{
for(int i = 1; i <= 3; i++)
{
#>
Hello <#=_field#> World <#= i #>!
<#+
}
}
#>

Resources