signature:
public class Images { /** * 为图片添加水印 , 可以设定透明度与水印的位置
 * 水印位置默认支持9种 , 分别是 :
 * TOP _ LEFT | TOP _ CENTER | TOP _ RIGHT CENTER _ LEFT | CENTER | CENTER _ RIGHT
 * BOTTOM _ LEFT | BOTTOM _ CENTER | BOTTOM _ RIGHT
 * @ param srcIm
 * 源图片
 * @ param markIm
 * 水印图片
 * @ param opacity
 * 透明度 , 要求大于0小于1 , 默认为0.5f
 * @ param pos
 * 共9个位置 , 请使用 Images . WATERMARK _ { XXX } 进行设置 , 默认为
 * Images . WATERMARK _ CENTER
 * @ param margin
 * 水印距离四周的边距 默认为0
 * @ return */
public static BufferedImage addWatermark ( Object srcIm , Object markIm , float opacity , int pos , int margin ) { } }

implementation:
BufferedImage im1 = read ( srcIm ) ; BufferedImage im2 = read ( markIm ) ; int cw = im1 . getWidth ( ) ; int ch = im1 . getHeight ( ) ; int mw = im2 . getWidth ( ) ; int mh = im2 . getHeight ( ) ; if ( opacity > 1 || opacity <= 0 ) { opacity = 0.5f ; } if ( pos > 9 || pos <= 0 ) { pos = 5 ; } // 计算水印位置
int px = 0 ; int py = 0 ; switch ( pos ) { case WATERMARK_TOP_LEFT : px = margin ; py = margin ; break ; case WATERMARK_TOP_CENTER : px = ( cw - mw ) / 2 ; py = margin ; break ; case WATERMARK_TOP_RIGHT : px = cw - mw - margin ; py = margin ; break ; case WATERMARK_CENTER_LEFT : px = margin ; py = ( ch - mh ) / 2 ; break ; case WATERMARK_CENTER : px = ( cw - mw ) / 2 ; py = ( ch - mh ) / 2 ; break ; case WATERMARK_CENTER_RIGHT : px = cw - mw - margin ; py = ( ch - mh ) / 2 ; break ; case WATERMARK_BOTTOM_LEFT : px = margin ; py = ch - mh - margin ; break ; case WATERMARK_BOTTOM_CENTER : px = ( cw - mw ) / 2 ; py = ch - mh - margin ; break ; case WATERMARK_BOTTOM_RIGHT : px = cw - mw - margin ; py = ch - mh - margin ; break ; } // 添加水印
Graphics2D gs = im1 . createGraphics ( ) ; gs . setComposite ( AlphaComposite . getInstance ( AlphaComposite . SRC_ATOP , opacity ) ) ; gs . drawImage ( im2 , px , py , null ) ; gs . dispose ( ) ; return im1 ;


signature:
public class Images { /** * 获取灰度图像
 * @ param srcIm
 * 源图片
 * @ return 灰度图片 */
public static BufferedImage grayImage ( Object srcIm ) { } }

implementation: BufferedImage srcImage = read ( srcIm ) ; BufferedImage grayImage = new BufferedImage ( srcImage . getWidth ( ) , srcImage . getHeight ( ) , srcImage . getType ( ) ) ; for ( int i = 0 ; i < srcImage . getWidth ( ) ; i ++ ) { for ( int j = 0 ; j < srcImage . getHeight ( ) ; j ++ ) { grayImage . setRGB ( i , j , Colors . getGray ( srcImage , i , j ) ) ; } } return grayImage ;


signature:
public class Images { /** * 实现两张图片的正片叠底效果
 * @ param bgIm
 * 背景图
 * @ param itemIm
 * 上层图
 * @ param x
 * 上层图横坐标
 * @ param y
 * 上层图横坐标
 * @ return 正片叠底后的图片 */
public static BufferedImage multiply ( Object bgIm , Object itemIm , int x , int y ) { } }

implementation:
BufferedImage viewportImage = read ( bgIm ) ; BufferedImage itemImage = read ( itemIm ) ; BufferedImage muImage = new BufferedImage ( viewportImage . getWidth ( ) , viewportImage . getHeight ( ) , viewportImage . getType ( ) ) ; // 背景图为视口范围 , 上层图不能超过视口进行绘制 , 只有重合部分进行计算叠底
int xMin = x ; int xMax = x + itemImage . getWidth ( ) ; int yMin = y ; int yMax = y + itemImage . getHeight ( ) ; for ( int i = 0 ; i < viewportImage . getWidth ( ) ; i ++ ) { for ( int j = 0 ; j < viewportImage . getHeight ( ) ; j ++ ) { int rgb = 0 ; // 判断是否重合
if ( i >= xMin && i < xMax && j >= yMin && j < yMax ) { // 获取两个图rgb值
int vpRGB = viewportImage . getRGB ( i , j ) ; int imRGB = itemImage . getRGB ( i - x , j - y ) ; rgb = Colors . getMultiply ( vpRGB , imRGB ) ; } else { rgb = viewportImage . getRGB ( i , j ) ; } muImage . setRGB ( i , j , rgb ) ; } } return muImage ;


signature:
public class Images { /** * 根据指定通道的亮度值 ( 灰度值 ) 来自动计算哪些像素需要扣掉 。
 * @ param srcIm
 * 源图片
 * @ param channel
 * 通道编号 , 0 : red 1 : green 2 : blue 其他 : 亮度
 * @ return 抠图后图片对象 */
public static BufferedImage cutoutByChannel ( Object srcIm , int channel ) { } }

implementation:
BufferedImage srcImage = read ( srcIm ) ; BufferedImage resultImage = new BufferedImage ( srcImage . getWidth ( ) , srcImage . getHeight ( ) , BufferedImage . TYPE_4BYTE_ABGR ) ; // 开始绘制
for ( int i = 0 ; i < srcImage . getWidth ( ) ; i ++ ) { for ( int j = 0 ; j < srcImage . getHeight ( ) ; j ++ ) { int pixel = srcImage . getRGB ( i , j ) ; int alpha = 0 ; switch ( channel ) { case CHANNEL_RED : alpha = Colors . getRGB ( pixel ) [ 0 ] ; break ; case CHANNEL_GREEN : alpha = Colors . getRGB ( pixel ) [ 1 ] ; break ; case CHANNEL_BLUE : alpha = Colors . getRGB ( pixel ) [ 2 ] ; break ; default : alpha = Colors . getLuminance ( srcImage , i , j ) ; break ; } pixel = ( alpha << 24 ) & 0xff000000 | ( pixel & 0x00ffffff ) ; resultImage . setRGB ( i , j , pixel ) ; } } return resultImage ;


signature:
public class Images { /** * 指定的像素点为背景色参考 , 在指定范围内的颜色将设置为透明 。
 * < / br >
 * ! ! ! 该方法适合背景与前景相差特别大的图片 , 最好是背景颜色基本一致 , 前景背景有明显分隔界限 。
 * @ param srcIm
 * 源图片
 * @ param x
 * 采样像素点横坐标
 * @ param y
 * 采样像素点纵坐标
 * @ param range
 * 采样像素可允许色差范围 , 数值越大去掉的颜色范围越多
 * @ return 抠图后图片对象 */
public static BufferedImage cutoutByPixel ( Object srcIm , int x , int y , int range ) { } }

implementation:
BufferedImage srcImage = read ( srcIm ) ; BufferedImage resultImage = new BufferedImage ( srcImage . getWidth ( ) , srcImage . getHeight ( ) , BufferedImage . TYPE_4BYTE_ABGR ) ; // 获取选样点
int [ ] srgb = Colors . getRGB ( srcImage . getRGB ( x , y ) ) ; // 开始绘制
for ( int i = 0 ; i < srcImage . getWidth ( ) ; i ++ ) { for ( int j = 0 ; j < srcImage . getHeight ( ) ; j ++ ) { int pixel = srcImage . getRGB ( i , j ) ; int [ ] crgb = Colors . getRGB ( pixel ) ; int alpha = 255 ; // 范围内的都干掉
if ( inRangeColor ( srgb , crgb , range ) ) { alpha = 0 ; } // 范围大一点点的 , 可能就需要半透明来处理了
else if ( inRangeColor ( srgb , crgb , ( int ) ( range * 1.5 ) ) ) { alpha = 64 ; } // 范围大一点点的 , 可能就需要半透明来处理了
else if ( inRangeColor ( srgb , crgb , range * 2 ) ) { alpha = 128 ; } // 不在范围的原样输出吧
else { alpha = Colors . getAlpha ( pixel ) ; } pixel = ( alpha << 24 ) & 0xff000000 | ( pixel & 0x00ffffff ) ; resultImage . setRGB ( i , j , pixel ) ; } } return resultImage ;


signature:
public class Images { /** * 获取三原色通道图片
 * @ param srcIm
 * 源图片
 * @ param channel
 * 通道编号 , 0 : red 1 : green 2 : blue
 * @ return 单一通道图片 */
public static BufferedImage channelImage ( Object srcIm , int channel ) { } }

implementation: BufferedImage srcImage = read ( srcIm ) ; BufferedImage rcImage = new BufferedImage ( srcImage . getWidth ( ) , srcImage . getHeight ( ) , srcImage . getType ( ) ) ; for ( int i = 0 ; i < srcImage . getWidth ( ) ; i ++ ) { for ( int j = 0 ; j < srcImage . getHeight ( ) ; j ++ ) { int r = Colors . getRGB ( srcImage , i , j ) [ channel ] ; rcImage . setRGB ( i , j , new Color ( r , r , r ) . getRGB ( ) ) ; } } return rcImage ;


signature:
public class Images { /** * 将一个图片文件读入内存
 * @ param img
 * 图片文件
 * @ return 图片对象 */
public static BufferedImage read ( Object img ) { } }

implementation:
try { if ( img instanceof BufferedImage ) { return ( BufferedImage ) img ; } if ( img instanceof CharSequence ) { return ImageIO . read ( Files . checkFile ( img . toString ( ) ) ) ; } if ( img instanceof File ) return ImageIO . read ( ( File ) img ) ; if ( img instanceof byte [ ] ) return ImageIO . read ( new ByteArrayInputStream ( ( byte [ ] ) img ) ) ; if ( img instanceof URL ) img = ( ( URL ) img ) . openStream ( ) ; if ( img instanceof InputStream ) { File tmp = File . createTempFile ( "nutz_img" , ".jpg" ) ; Files . write ( tmp , img ) ; try { return read ( tmp ) ; } finally { tmp . delete ( ) ; } } throw Lang . makeThrow ( "Unkown img info!! --> " + img ) ; } catch ( IOException e ) { try { InputStream in = null ; if ( img instanceof File ) in = new FileInputStream ( ( File ) img ) ; else if ( img instanceof URL ) in = ( ( URL ) img ) . openStream ( ) ; else if ( img instanceof InputStream ) in = ( InputStream ) img ; if ( in != null ) return readJpeg ( in ) ; } catch ( IOException e2 ) { e2 . fillInStackTrace ( ) ; } return null ; // throw Lang . wrapThrow ( e ) ;
}


signature:
public class Images { /** * 将内存中一个图片写入目标文件
 * @ param im
 * 图片对象
 * @ param targetFile
 * 目标文件 , 根据其后缀 , 来决定写入何种图片格式 */
public static void write ( RenderedImage im , File targetFile ) { } }

implementation: try { ImageIO . write ( im , Files . getSuffixName ( targetFile ) , targetFile ) ; } catch ( IOException e ) { throw Lang . wrapThrow ( e ) ; }


signature:
public class Images { /** * 将内存中的一个写入输出流
 * @ param im
 * 图片对象
 * @ param imFormat
 * 图片格式
 * @ param out
 * 输出流 */
public static void write ( RenderedImage im , String imFormat , OutputStream out ) { } }

implementation: try { ImageIO . write ( im , imFormat , out ) ; } catch ( IOException e ) { throw Lang . wrapThrow ( e ) ; }


signature:
public class Images { /** * 写入一个 JPG 图像
 * @ param im
 * 图像对象
 * @ param targetJpg
 * 目标输出 JPG 图像文件
 * @ param quality
 * 质量 0.1f ~ 1.0f */
public static void writeJpeg ( RenderedImage im , Object targetJpg , float quality ) { } }

implementation: ImageWriter writer = null ; try { writer = ImageIO . getImageWritersBySuffix ( "jpg" ) . next ( ) ; ImageWriteParam param = writer . getDefaultWriteParam ( ) ; param . setCompressionMode ( ImageWriteParam . MODE_EXPLICIT ) ; param . setCompressionQuality ( quality ) ; ImageOutputStream os = ImageIO . createImageOutputStream ( targetJpg ) ; writer . setOutput ( os ) ; writer . write ( ( IIOMetadata ) null , new IIOImage ( im , null , null ) , param ) ; os . flush ( ) ; os . close ( ) ; } catch ( IOException e ) { throw Lang . wrapThrow ( e ) ; } finally { if ( writer != null ) { try { writer . dispose ( ) ; } catch ( Throwable e ) { } } }


signature:
public class Images { /** * 尝试读取JPEG文件的高级方法 , 可读取32位的jpeg文件
 * 来自 :
 * http : / / stackoverflow . com / questions / 2408613 / problem - reading - jpeg - image -
 * using - imageio - readfile - file */
private static BufferedImage readJpeg ( InputStream in ) throws IOException { } }

implementation:
Iterator < ImageReader > readers = ImageIO . getImageReadersByFormatName ( "JPEG" ) ; ImageReader reader = null ; while ( readers . hasNext ( ) ) { reader = readers . next ( ) ; if ( reader . canReadRaster ( ) ) { break ; } } if ( reader == null ) return null ; try { ImageInputStream input = ImageIO . createImageInputStream ( in ) ; reader . setInput ( input ) ; // Read the image raster
Raster raster = reader . readRaster ( 0 , null ) ; BufferedImage image = createJPEG4 ( raster ) ; ByteArrayOutputStream out = new ByteArrayOutputStream ( ) ; writeJpeg ( image , out , 1 ) ; out . flush ( ) ; return read ( new ByteArrayInputStream ( out . toByteArray ( ) ) ) ; } finally { try { reader . dispose ( ) ; } catch ( Throwable e ) { } }


signature:
public class Images { /** * Java ' s ImageIO can ' t process 4 - component images and Java2D can ' t apply
 * AffineTransformOp either , so convert raster data to RGB . Technique due to
 * MArk Stephens . Free for any use . */
private static BufferedImage createJPEG4 ( Raster raster ) { } }

implementation: int w = raster . getWidth ( ) ; int h = raster . getHeight ( ) ; byte [ ] rgb = new byte [ w * h * 3 ] ; float [ ] Y = raster . getSamples ( 0 , 0 , w , h , 0 , ( float [ ] ) null ) ; float [ ] Cb = raster . getSamples ( 0 , 0 , w , h , 1 , ( float [ ] ) null ) ; float [ ] Cr = raster . getSamples ( 0 , 0 , w , h , 2 , ( float [ ] ) null ) ; float [ ] K = raster . getSamples ( 0 , 0 , w , h , 3 , ( float [ ] ) null ) ; for ( int i = 0 , imax = Y . length , base = 0 ; i < imax ; i ++ , base += 3 ) { float k = 220 - K [ i ] , y = 255 - Y [ i ] , cb = 255 - Cb [ i ] , cr = 255 - Cr [ i ] ; double val = y + 1.402 * ( cr - 128 ) - k ; val = ( val - 128 ) * .65f + 128 ; rgb [ base ] = val < 0.0 ? ( byte ) 0 : val > 255.0 ? ( byte ) 0xff : ( byte ) ( val + 0.5 ) ; val = y - 0.34414 * ( cb - 128 ) - 0.71414 * ( cr - 128 ) - k ; val = ( val - 128 ) * .65f + 128 ; rgb [ base + 1 ] = val < 0.0 ? ( byte ) 0 : val > 255.0 ? ( byte ) 0xff : ( byte ) ( val + 0.5 ) ; val = y + 1.772 * ( cb - 128 ) - k ; val = ( val - 128 ) * .65f + 128 ; rgb [ base + 2 ] = val < 0.0 ? ( byte ) 0 : val > 255.0 ? ( byte ) 0xff : ( byte ) ( val + 0.5 ) ; } raster = Raster . createInterleavedRaster ( new DataBufferByte ( rgb , rgb . length ) , w , h , w * 3 , 3 , new int [ ] { 0 , 1 , 2 } , null ) ; ColorSpace cs = ColorSpace . getInstance ( ColorSpace . CS_sRGB ) ; ColorModel cm = new ComponentColorModel ( cs , false , true , Transparency . OPAQUE , DataBuffer . TYPE_BYTE ) ; return new BufferedImage ( cm , ( WritableRaster ) raster , true , null ) ;


signature:
public class Images { /** * 生成该图片对应的 Base64 编码的字符串
 * @ param targetFile
 * 图片文件
 * @ return 图片对应的 Base64 编码的字符串 */
public static String encodeBase64 ( File targetFile ) { } }

implementation: BufferedImage image = null ; try { image = ImageIO . read ( targetFile ) ; } catch ( IOException e ) { throw Lang . wrapThrow ( e ) ; } ByteArrayOutputStream baos = new ByteArrayOutputStream ( ) ; BufferedOutputStream bos = new BufferedOutputStream ( baos ) ; image . flush ( ) ; try { ImageIO . write ( image , Files . getSuffixName ( targetFile ) , bos ) ; bos . flush ( ) ; bos . close ( ) ; } catch ( IOException e ) { throw Lang . wrapThrow ( e ) ; } byte [ ] bImage = baos . toByteArray ( ) ; return Base64 . encodeToString ( bImage , false ) ;


signature:
public class Images { /** * 在一个RGB画布上重新绘制Image , 解决CMYK图像偏色的问题 */
public static BufferedImage redraw ( BufferedImage img , Color bg ) { } }

implementation: BufferedImage rgbImage = new BufferedImage ( img . getWidth ( ) , img . getHeight ( ) , BufferedImage . TYPE_3BYTE_BGR ) ; Graphics2D g2d = rgbImage . createGraphics ( ) ; g2d . drawImage ( img , 0 , 0 , bg , null ) ; g2d . dispose ( ) ; return rgbImage ;


signature:
public class Images { /** * 文字生成图片 , 黑底白字 。
 * @ param content
 * 文字内容
 * @ return 图像 */
public static BufferedImage createText ( String content ) { } }

implementation: return createText ( content , 0 , 0 , null , null , null , 0 , Font . PLAIN ) ;


signature:
public class Images { /** * 文字生成图片
 * @ param content
 * 文字内容
 * @ param width
 * 图片宽度 , 默认256
 * @ param height
 * 图片高度 , 默认256
 * @ param fontColor
 * 文字颜色 默认白色
 * @ param bgColor
 * 背景颜色 默认黑色
 * @ param fontName
 * 字体名称 需运行环境中已有该字体名称
 * @ param fontSize
 * 字体大小
 * @ param fontStyle
 * 字体样式 Font . PLAIN | | Font . BOLD | | Font . ITALIC
 * @ return 图像 */
public static BufferedImage createText ( String content , int width , int height , String fontColor , String bgColor , String fontName , int fontSize , int fontStyle ) { } }

implementation:
// 处理下参数
if ( Strings . isBlank ( content ) ) { return null ; } if ( width <= 0 ) { width = 256 ; } if ( height <= 0 ) { height = 256 ; } if ( Strings . isBlank ( fontColor ) ) { fontColor = "#FFF" ; } if ( Strings . isBlank ( bgColor ) ) { bgColor = "#000" ; } if ( fontSize <= 0 ) { fontSize = height / 2 ; } if ( fontStyle < 0 || fontStyle > 2 ) { fontStyle = Font . BOLD ; } // 准备
BufferedImage im ; Graphics2D gc ; Color colorFont = Colors . as ( fontColor ) ; Color colorBg = Colors . as ( bgColor ) ; // 判断图片格式
int imageType = BufferedImage . TYPE_INT_RGB ; if ( colorFont . getAlpha ( ) < 255 || colorBg . getAlpha ( ) < 255 ) { imageType = BufferedImage . TYPE_INT_ARGB ; } // 生成背景
im = new BufferedImage ( width , height , imageType ) ; gc = im . createGraphics ( ) ; gc . setRenderingHint ( RenderingHints . KEY_ANTIALIASING , RenderingHints . VALUE_ANTIALIAS_ON ) ; gc . setBackground ( colorBg ) ; gc . clearRect ( 0 , 0 , width , height ) ; // 写入文字
Font cFont = Fonts . get ( fontName , fontStyle , fontSize ) ; gc . setColor ( colorFont ) ; gc . setFont ( cFont ) ; FontMetrics cFontM = gc . getFontMetrics ( cFont ) ; int cW = cFontM . stringWidth ( content ) ; int ascent = cFontM . getAscent ( ) ; // 取得Ascent
int descent = cFontM . getDescent ( ) ; // 取得Descent
int x , y ; x = width / 2 - cW / 2 ; y = ( height - ( ascent + descent ) ) / 2 + ascent ; gc . drawString ( content , x , y ) ; return im ;


signature:
public class Images { /** * 根据名字生成头像 , 英文采用第一个字母 , 中文2个字使用2个字 , 超过2个字采用第一个字
 * @ param name
 * 名字
 * @ return 头像 */
public static BufferedImage createAvatar ( String name ) { } }

implementation: return createAvatar ( name , 0 , null , null , null , 0 , Font . BOLD ) ;


signature:
public class Images { /** * 根据名字生成头像 , 英文采用第一个字母 , 中文2个字使用2个字 , 超过2个字采用第一个字
 * @ param name
 * 名字
 * @ param size
 * 图片大小 , 默认256
 * @ param fontColor
 * 文字颜色 默认白色
 * @ param bgColor
 * 背景颜色 默认黑色
 * @ param fontName
 * 字体名称 需运行环境中已有该字体名称
 * @ param fontSize
 * 字体大小
 * @ param fontStyle
 * 字体样式 Font . PLAIN | | Font . BOLD | | Font . ITALIC
 * @ return 头像 */
public static BufferedImage createAvatar ( String name , int size , String fontColor , String bgColor , String fontName , int fontSize , int fontStyle ) { } }

implementation:
// 检查输入项目
if ( Strings . isBlank ( name ) ) { return null ; } // 分析要写入的文字
String content = name ; if ( name . length ( ) > 2 ) { content = ( "" + name . charAt ( 0 ) ) ; } content = content . toUpperCase ( ) ; return createText ( content , size , size , fontColor , bgColor , fontName , fontSize , fontStyle ) ;


signature:
public class Images { /** * 根据指定文字内容 , 生成验证码
 * @ param content
 * 文字内容
 * @ param width
 * 图片宽度
 * @ param height
 * 图片高度
 * @ param fontColor
 * 文字颜色 默认黑色
 * @ param bgColor
 * 背景颜色 默认白色
 * @ return 图像 */
public static BufferedImage createCaptcha ( String content , int width , int height , String fontColor , String bgColor , String fontName ) { } }

implementation:
// 处理下参数
if ( Strings . isBlank ( content ) ) { return null ; } boolean isChinese = Strings . isChineseCharacter ( content . charAt ( 0 ) ) ; if ( width <= 0 ) { // 中文字体的话 , 间距需要多一些
width = content . length ( ) * ( isChinese ? 25 : 20 ) + 20 ; } if ( height <= 0 ) { height = 30 ; } Color userColor = Strings . isBlank ( fontColor ) ? null : Colors . as ( fontColor ) ; Color colorBg = Strings . isBlank ( bgColor ) ? Colors . randomColor ( ) : Colors . as ( bgColor ) ; // 生成背景
BufferedImage im = new BufferedImage ( width , height , BufferedImage . TYPE_INT_RGB ) ; Graphics2D gc = im . createGraphics ( ) ; gc . setRenderingHint ( RenderingHints . KEY_ANTIALIASING , RenderingHints . VALUE_ANTIALIAS_ON ) ; gc . setBackground ( colorBg ) ; gc . clearRect ( 0 , 0 , width , height ) ; // 加入干扰线
for ( int i = 0 ; i < 7 ; i ++ ) { gc . setColor ( userColor == null ? Colors . randomColor ( 5 , 250 ) : userColor ) ; int x = R . random ( 0 , width ) ; int y = R . random ( 0 , height ) ; int x1 = R . random ( 0 , width ) ; int y1 = R . random ( 0 , height ) ; gc . drawLine ( x , y , x1 , y1 ) ; } // 写入文字
int rx = 10 ; int ry = isChinese ? height - 8 : height - 10 ; for ( int i = 0 ; i < content . length ( ) ; i ++ ) { int fontStyle = R . random ( 0 , 3 ) ; int fontSize = R . random ( height - 10 , height - 5 ) ; Font textFont = Strings . isBlank ( fontName ) ? Fonts . random ( fontStyle , fontSize ) : Fonts . get ( fontName , fontStyle , fontSize ) ; gc . setColor ( userColor == null ? Colors . randomColor ( 10 , 250 ) : userColor ) ; gc . setFont ( textFont ) ; // 设置字体旋转角度
int degree = R . random ( 0 , 64 ) % 30 ; // 正向角度
gc . rotate ( degree * Math . PI / 180 , rx , ry ) ; gc . drawString ( content . charAt ( i ) + "" , rx , ry ) ; // 反向角度
gc . rotate ( - degree * Math . PI / 180 , rx , ry ) ; rx += ( isChinese ? 5 : 0 ) + width / ( content . length ( ) + 2 ) ; } // 图像扭曲
im = twist ( im , 1 , bgColor ) ; return im ;


signature:
public class MethodVisitor { /** * Visits a parameter of this method .
 * @ param name
 * parameter name or null if none is provided .
 * @ param access
 * the parameter ' s access flags , only < tt > ACC _ FINAL < / tt > ,
 * < tt > ACC _ SYNTHETIC < / tt > or / and < tt > ACC _ MANDATED < / tt > are
 * allowed ( see { @ link Opcodes } ) . */
public void visitParameter ( String name , int access ) { } }

implementation: if ( api < Opcodes . ASM5 ) { throw new RuntimeException ( ) ; } if ( mv != null ) { mv . visitParameter ( name , access ) ; }


signature:
public class MethodVisitor { /** * Visits an annotation of this method .
 * @ param desc
 * the class descriptor of the annotation class .
 * @ param visible
 * < tt > true < / tt > if the annotation is visible at runtime .
 * @ return a visitor to visit the annotation values , or < tt > null < / tt > if
 * this visitor is not interested in visiting this annotation . */
public AnnotationVisitor visitAnnotation ( String desc , boolean visible ) { } }

implementation: if ( mv != null ) { return mv . visitAnnotation ( desc , visible ) ; } return null ;


signature:
public class MethodVisitor { /** * Visits an annotation of a parameter this method .
 * @ param parameter
 * the parameter index .
 * @ param desc
 * the class descriptor of the annotation class .
 * @ param visible
 * < tt > true < / tt > if the annotation is visible at runtime .
 * @ return a visitor to visit the annotation values , or < tt > null < / tt > if
 * this visitor is not interested in visiting this annotation . */
public AnnotationVisitor visitParameterAnnotation ( int parameter , String desc , boolean visible ) { } }

implementation: if ( mv != null ) { return mv . visitParameterAnnotation ( parameter , desc , visible ) ; } return null ;


signature:
public class MethodVisitor { /** * Visits the current state of the local variables and operand stack
 * elements . This method must ( * ) be called < i > just before < / i > any
 * instruction < b > i < / b > that follows an unconditional branch instruction
 * such as GOTO or THROW , that is the target of a jump instruction , or that
 * starts an exception handler block . The visited types must describe the
 * values of the local variables and of the operand stack elements < i > just
 * before < / i > < b > i < / b > is executed . < br >
 * < br >
 * ( * ) this is mandatory only for classes whose version is greater than or
 * equal to { @ link Opcodes # V1_6 V1_6 } . < br >
 * < br >
 * The frames of a method must be given either in expanded form , or in
 * compressed form ( all frames must use the same format , i . e . you must not
 * mix expanded and compressed frames within a single method ) :
 * < ul >
 * < li > In expanded form , all frames must have the F _ NEW type . < / li >
 * < li > In compressed form , frames are basically " deltas " from the state of
 * the previous frame :
 * < ul >
 * < li > { @ link Opcodes # F _ SAME } representing frame with exactly the same
 * locals as the previous frame and with the empty stack . < / li >
 * < li > { @ link Opcodes # F _ SAME1 } representing frame with exactly the same
 * locals as the previous frame and with single value on the stack (
 * < code > nStack < / code > is 1 and < code > stack [ 0 ] < / code > contains value for the
 * type of the stack item ) . < / li >
 * < li > { @ link Opcodes # F _ APPEND } representing frame with current locals are
 * the same as the locals in the previous frame , except that additional
 * locals are defined ( < code > nLocal < / code > is 1 , 2 or 3 and
 * < code > local < / code > elements contains values representing added types ) . < / li >
 * < li > { @ link Opcodes # F _ CHOP } representing frame with current locals are the
 * same as the locals in the previous frame , except that the last 1-3 locals
 * are absent and with the empty stack ( < code > nLocals < / code > is 1 , 2 or 3 ) . < / li >
 * < li > { @ link Opcodes # F _ FULL } representing complete frame data . < / li >
 * < / ul >
 * < / li >
 * < / ul >
 * < br >
 * In both cases the first frame , corresponding to the method ' s parameters
 * and access flags , is implicit and must not be visited . Also , it is
 * illegal to visit two or more frames for the same code location ( i . e . , at
 * least one instruction must be visited between two calls to visitFrame ) .
 * @ param type
 * the type of this stack map frame . Must be
 * { @ link Opcodes # F _ NEW } for expanded frames , or
 * { @ link Opcodes # F _ FULL } , { @ link Opcodes # F _ APPEND } ,
 * { @ link Opcodes # F _ CHOP } , { @ link Opcodes # F _ SAME } or
 * { @ link Opcodes # F _ APPEND } , { @ link Opcodes # F _ SAME1 } for
 * compressed frames .
 * @ param nLocal
 * the number of local variables in the visited frame .
 * @ param local
 * the local variable types in this frame . This array must not be
 * modified . Primitive types are represented by
 * { @ link Opcodes # TOP } , { @ link Opcodes # INTEGER } ,
 * { @ link Opcodes # FLOAT } , { @ link Opcodes # LONG } ,
 * { @ link Opcodes # DOUBLE } , { @ link Opcodes # NULL } or
 * { @ link Opcodes # UNINITIALIZED _ THIS } ( long and double are
 * represented by a single element ) . Reference types are
 * represented by String objects ( representing internal names ) ,
 * and uninitialized types by Label objects ( this label
 * designates the NEW instruction that created this uninitialized
 * value ) .
 * @ param nStack
 * the number of operand stack elements in the visited frame .
 * @ param stack
 * the operand stack types in this frame . This array must not be
 * modified . Its content has the same format as the " local "
 * array .
 * @ throws IllegalStateException
 * if a frame is visited just after another one , without any
 * instruction between the two ( unless this frame is a
 * Opcodes # F _ SAME frame , in which case it is silently ignored ) . */
public void visitFrame ( int type , int nLocal , Object [ ] local , int nStack , Object [ ] stack ) { } }

implementation: if ( mv != null ) { mv . visitFrame ( type , nLocal , local , nStack , stack ) ; }


signature:
public class MethodVisitor { /** * Visits a type instruction . A type instruction is an instruction that
 * takes the internal name of a class as parameter .
 * @ param opcode
 * the opcode of the type instruction to be visited . This opcode
 * is either NEW , ANEWARRAY , CHECKCAST or INSTANCEOF .
 * @ param type
 * the operand of the instruction to be visited . This operand
 * must be the internal name of an object or array class ( see
 * { @ link Type # getInternalName ( ) getInternalName } ) . */
public void visitTypeInsn ( int opcode , String type ) { } }

implementation: if ( mv != null ) { mv . visitTypeInsn ( opcode , type ) ; }


signature:
public class MethodVisitor { /** * Visits a field instruction . A field instruction is an instruction that
 * loads or stores the value of a field of an object .
 * @ param opcode
 * the opcode of the type instruction to be visited . This opcode
 * is either GETSTATIC , PUTSTATIC , GETFIELD or PUTFIELD .
 * @ param owner
 * the internal name of the field ' s owner class ( see
 * { @ link Type # getInternalName ( ) getInternalName } ) .
 * @ param name
 * the field ' s name .
 * @ param desc
 * the field ' s descriptor ( see { @ link Type Type } ) . */
public void visitFieldInsn ( int opcode , String owner , String name , String desc ) { } }

implementation: if ( mv != null ) { mv . visitFieldInsn ( opcode , owner , name , desc ) ; }


signature:
public class MethodVisitor { /** * Visits a method instruction . A method instruction is an instruction that
 * invokes a method .
 * @ param opcode
 * the opcode of the type instruction to be visited . This opcode
 * is either INVOKEVIRTUAL , INVOKESPECIAL , INVOKESTATIC or
 * INVOKEINTERFACE .
 * @ param owner
 * the internal name of the method ' s owner class ( see
 * { @ link Type # getInternalName ( ) getInternalName } ) .
 * @ param name
 * the method ' s name .
 * @ param desc
 * the method ' s descriptor ( see { @ link Type Type } ) . */
@ Deprecated public void visitMethodInsn ( int opcode , String owner , String name , String desc ) { } }

implementation: if ( api >= Opcodes . ASM5 ) { boolean itf = opcode == Opcodes . INVOKEINTERFACE ; visitMethodInsn ( opcode , owner , name , desc , itf ) ; return ; } if ( mv != null ) { mv . visitMethodInsn ( opcode , owner , name , desc ) ; }


signature:
public class MethodVisitor { /** * Visits a TABLESWITCH instruction .
 * @ param min
 * the minimum key value .
 * @ param max
 * the maximum key value .
 * @ param dflt
 * beginning of the default handler block .
 * @ param labels
 * beginnings of the handler blocks . < tt > labels [ i ] < / tt > is the
 * beginning of the handler block for the < tt > min + i < / tt > key . */
public void visitTableSwitchInsn ( int min , int max , Label dflt , Label ... labels ) { } }

implementation: if ( mv != null ) { mv . visitTableSwitchInsn ( min , max , dflt , labels ) ; }


signature:
public class MethodVisitor { /** * Visits a LOOKUPSWITCH instruction .
 * @ param dflt
 * beginning of the default handler block .
 * @ param keys
 * the values of the keys .
 * @ param labels
 * beginnings of the handler blocks . < tt > labels [ i ] < / tt > is the
 * beginning of the handler block for the < tt > keys [ i ] < / tt > key . */
public void visitLookupSwitchInsn ( Label dflt , int [ ] keys , Label [ ] labels ) { } }

implementation: if ( mv != null ) { mv . visitLookupSwitchInsn ( dflt , keys , labels ) ; }


signature:
public class MethodVisitor { /** * Visits a MULTIANEWARRAY instruction .
 * @ param desc
 * an array type descriptor ( see { @ link Type Type } ) .
 * @ param dims
 * number of dimensions of the array to allocate . */
public void visitMultiANewArrayInsn ( String desc , int dims ) { } }

implementation: if ( mv != null ) { mv . visitMultiANewArrayInsn ( desc , dims ) ; }


signature:
public class MethodVisitor { /** * Visits an annotation on a local variable type .
 * @ param typeRef
 * a reference to the annotated type . The sort of this type
 * reference must be { @ link TypeReference # LOCAL _ VARIABLE
 * LOCAL _ VARIABLE } or { @ link TypeReference # RESOURCE _ VARIABLE
 * RESOURCE _ VARIABLE } . See { @ link TypeReference } .
 * @ param typePath
 * the path to the annotated type argument , wildcard bound , array
 * element type , or static inner type within ' typeRef ' . May be
 * < tt > null < / tt > if the annotation targets ' typeRef ' as a whole .
 * @ param start
 * the fist instructions corresponding to the continuous ranges
 * that make the scope of this local variable ( inclusive ) .
 * @ param end
 * the last instructions corresponding to the continuous ranges
 * that make the scope of this local variable ( exclusive ) . This
 * array must have the same size as the ' start ' array .
 * @ param index
 * the local variable ' s index in each range . This array must have
 * the same size as the ' start ' array .
 * @ param desc
 * the class descriptor of the annotation class .
 * @ param visible
 * < tt > true < / tt > if the annotation is visible at runtime .
 * @ return a visitor to visit the annotation values , or < tt > null < / tt > if
 * this visitor is not interested in visiting this annotation . */
public AnnotationVisitor visitLocalVariableAnnotation ( int typeRef , TypePath typePath , Label [ ] start , Label [ ] end , int [ ] index , String desc , boolean visible ) { } }

implementation: if ( api < Opcodes . ASM5 ) { throw new RuntimeException ( ) ; } if ( mv != null ) { return mv . visitLocalVariableAnnotation ( typeRef , typePath , start , end , index , desc , visible ) ; } return null ;


signature:
public class MethodVisitor { /** * Visits a line number declaration .
 * @ param line
 * a line number . This number refers to the source file from
 * which the class was compiled .
 * @ param start
 * the first instruction corresponding to this line number .
 * @ throws IllegalArgumentException
 * if < tt > start < / tt > has not already been visited by this
 * visitor ( by the { @ link # visitLabel visitLabel } method ) . */
public void visitLineNumber ( int line , Label start ) { } }

implementation: if ( mv != null ) { mv . visitLineNumber ( line , start ) ; }


signature:
public class MvcI18n { /** * 取得国际化信息并格式化
 * { 0 } 帐号登录 { 1 } - > > test帐号登录失败
 * @ param key
 * @ return */
public static String message ( String key , Object ... params ) { } }

implementation: return MessageFormat . format ( messageOrDefault ( key , "" ) , params ) ;


signature:
public class MvcI18n { /** * 取得国际化信息并格式化
 * { 0 } 帐号登录 { 1 } - > > test帐号登录失败
 * @ param key
 * @ return */
public static String messageOrDefaultFormat ( String key , String defaultValue , Object ... params ) { } }

implementation: return MessageFormat . format ( messageOrDefault ( key , defaultValue ) , params ) ;


signature:
public class MvcI18n { /** * 取得国际化信息
 * @ param key
 * @ return */
public static String messageOrDefault ( String key , String defaultValue ) { } }

implementation: String localizationKey = Mvcs . getLocalizationKey ( ) == null ? Mvcs . getDefaultLocalizationKey ( ) : Mvcs . getLocalizationKey ( ) ; Map < String , Object > localization = Mvcs . getLocaleMessage ( localizationKey ) ; if ( null != localization ) { Object value = localization . get ( key ) ; return value == null ? defaultValue : String . valueOf ( value ) ; } return defaultValue ;


signature:
public class SqlExpressionGroup { /** * 用法
 * cnd . where ( ) . andInBySql ( " dept _ id " , " SELECT id FROM sys _ dept WHERE FIND _ IN _ SET ( ' % s ' , ancestors ) " , deptId ) ;
 * @ param name 查询条件
 * @ param subSql sql
 * @ param args 参数
 * @ return */
public SqlExpressionGroup andInBySql ( String name , String subSql , Object ... args ) { } }

implementation: return and ( inSql ( name , subSql , args ) ) ;


signature:
public class SqlExpressionGroup { /** * - - - - - between */
public SqlExpressionGroup andBetween ( String name , Object min , Object max ) { } }

implementation: return and ( new BetweenExpression ( name , min , max ) ) ;


signature:
public class InterceptorChain { /** * 继续执行下一个拦截器 , 如果已经没有剩下的拦截器 , 则执行原方法
 * @ return 拦截器链本身
 * @ throws Throwable
 * 下层拦截器或原方法抛出的一切异常 */
public InterceptorChain doChain ( ) throws Throwable { } }

implementation: if ( currentMI == miList . size ( ) ) invoke ( ) ; else { currentMI ++ ; miList . get ( currentMI - 1 ) . filter ( this ) ; } return this ;


signature:
public class InterceptorChain { /** * 执行原方法 , 一般情况下不应该直接被调用
 * @ throws Throwable
 * 原方法抛出的一切异常 */
public void invoke ( ) throws Throwable { } }

implementation: if ( invoked ) log . warnf ( "!! Calling Method more than once! Method --> %s" , callingMethod . toString ( ) ) ; else invoked = true ; this . returnValue = callingObj . _aop_invoke ( methodIndex , args ) ;


signature:
public class LRUCache { /** * Returns a < code > Collection < / code > that contains a copy of all cache
 * entries .
 * @ return a < code > Collection < / code > with a copy of the cache content . */
public synchronized Collection < Map . Entry < K , V > > getAll ( ) { } }

implementation: return new ArrayList < Map . Entry < K , V > > ( map . entrySet ( ) ) ;


signature:
public class Trans { /** * 是否在事务中
 * @ return 真 , 如果在不事务中 */
public static boolean isTransactionNone ( ) { } }

implementation: Transaction t = trans . get ( ) ; return null == t || t . getLevel ( ) == Connection . TRANSACTION_NONE ;


signature:
public class Trans { /** * 执行一组原子操作 , 并指定事务级别 。
 * 这里需要注意的是 , Nutz 支持事务模板的无限层级嵌套 。 这里 , 如果每一层嵌套 , 指定的事务级别有所不同 , 不同的数据库 , 可能引发不可预知的错误 。
 * 所以 , 嵌套的事务模板的事务 , 将以最顶层的事务为级别为标准 。 就是说 , 如果最顶层的事务级别为
 * ' TRANSACTION _ READ _ COMMITTED ' , 那么下面所包含的所有事务 , 无论你指定什么样的事务级别 , 都是
 * ' TRANSACTION _ READ _ COMMITTED ' , 这一点 , 由抽象类 Transaction 来保证 。 其 setLevel
 * 当被设置了一个大于 0 的整数以后 , 将不再 接受任何其他的值 。
 * 你可以通过继承 Transaction 来修改这个默认的行为 , 当然 , 这个行为修改一般是没有必要的 。
 * 另外 , 你还可能需要知道 , 通过 Trans . setup 方法 , 能让整个虚拟机的 Nutz 事务操作都使用你的 Transaction 实现
 * @ param level
 * 事务的级别 。
 * 你可以设置的事务级别是 :
 * < ul >
 * < li > java . sql . Connection . TRANSACTION _ NONE
 * < li > java . sql . Connection . TRANSACTION _ READ _ UNCOMMITTED
 * < li > java . sql . Connection . TRANSACTION _ READ _ COMMITTED
 * < li > java . sql . Connection . TRANSACTION _ REPEATABLE _ READ
 * < li > java . sql . Connection . TRANSACTION _ SERIALIZABLE
 * < / ul >
 * 不同的数据库 , 对于 JDBC 事务级别的规范 , 支持的力度不同 。 请参看相应数据库的文档 , 已
 * 确定你设置的数据库事务级别是否被支持 。
 * @ param atoms
 * 原子操作对象
 * @ see org . nutz . trans . Transaction
 * @ see java . sql . Connection */
public static void exec ( int level , Atom ... atoms ) { } }

implementation: if ( null == atoms ) return ; int num = count . get ( ) == null ? 0 : count . get ( ) ; try { _begain ( level ) ; for ( Atom atom : atoms ) atom . run ( ) ; _commit ( ) ; } catch ( Throwable e ) { _rollback ( num ) ; throw Lang . wrapThrow ( e ) ; } finally { _depose ( ) ; }


signature:
public class Trans { /** * 执行一个分子 , 并给出返回值
 * @ param < T >
 * @ param molecule
 * 分子
 * @ return 分子返回值 */
public static < T > T exec ( Molecule < T > molecule ) { } }

implementation: Trans . exec ( ( Atom ) molecule ) ; return molecule . getObj ( ) ;


signature:
public class Trans { /** * 回滚事务 , 执行它前 , 你必需保证你已经手工开始了一个事务
 * @ throws Exception */
public static void rollback ( ) throws Exception { } }

implementation: Integer c = Trans . count . get ( ) ; if ( c == null ) c = Integer . valueOf ( 0 ) ; else if ( c > 0 ) c -- ; Trans . _rollback ( c ) ;


signature:
public class Trans { /** * 如果在事务中 , 则返回事务的连接 , 否则直接从数据源取一个新的连接 */
public static Connection getConnectionAuto ( DataSource ds ) throws SQLException { } }

implementation: if ( get ( ) == null ) return ds . getConnection ( ) ; else return get ( ) . getConnection ( ds ) ;


signature:
public class Trans { /** * 自动判断是否关闭当前连接
 * @ param conn 数据库连接 */
public static void closeConnectionAuto ( Connection conn ) { } }

implementation: if ( get ( ) == null && null != conn ) { try { conn . close ( ) ; } catch ( SQLException e ) { throw Lang . wrapThrow ( e ) ; } }


signature:
public class Trans { /** * 强制清理事务上下文
 * @ param rollbackOrCommit 检测到未闭合的事务时回滚还是提交 , true为回滚 , false为提交 。 */
public static void clear ( boolean rollbackOrCommit ) { } }

implementation: Integer c = Trans . count . get ( ) ; if ( c == null ) return ; if ( c > 0 ) { for ( int i = 0 ; i < c ; i ++ ) { try { if ( rollbackOrCommit ) Trans . rollback ( ) ; else Trans . commit ( ) ; Trans . close ( ) ; } catch ( Exception e ) { } } } Trans . count . set ( null ) ; Transaction t = get ( ) ; if ( t != null ) t . close ( ) ; Trans . trans . set ( null ) ;


signature:
public class ClassReader { /** * Copies the bootstrap method data into the given { @ link ClassWriter } .
 * Should be called before the { @ link # accept ( ClassVisitor , int ) } method .
 * @ param classWriter
 * the { @ link ClassWriter } to copy bootstrap methods into . */
private void copyBootstrapMethods ( final ClassWriter classWriter , final Item [ ] items , final char [ ] c ) { } }

implementation:
// finds the " BootstrapMethods " attribute
int u = getAttributes ( ) ; boolean found = false ; for ( int i = readUnsignedShort ( u ) ; i > 0 ; -- i ) { String attrName = readUTF8 ( u + 2 , c ) ; if ( "BootstrapMethods" . equals ( attrName ) ) { found = true ; break ; } u += 6 + readInt ( u + 4 ) ; } if ( ! found ) { return ; } // copies the bootstrap methods in the class writer
int boostrapMethodCount = readUnsignedShort ( u + 8 ) ; for ( int j = 0 , v = u + 10 ; j < boostrapMethodCount ; j ++ ) { int position = v - u - 10 ; int hashCode = readConst ( readUnsignedShort ( v ) , c ) . hashCode ( ) ; for ( int k = readUnsignedShort ( v + 2 ) ; k > 0 ; -- k ) { hashCode ^= readConst ( readUnsignedShort ( v + 4 ) , c ) . hashCode ( ) ; v += 2 ; } v += 4 ; Item item = new Item ( j ) ; item . set ( position , hashCode & 0x7FFFFFFF ) ; int index = item . hashCode % items . length ; item . next = items [ index ] ; items [ index ] = item ; } int attrSize = readInt ( u + 4 ) ; ByteVector bootstrapMethods = new ByteVector ( attrSize + 62 ) ; bootstrapMethods . putByteArray ( b , u + 10 , attrSize - 2 ) ; classWriter . bootstrapMethodsCount = boostrapMethodCount ; classWriter . bootstrapMethods = bootstrapMethods ;


signature:
public class ClassReader { /** * Reads a field and makes the given visitor visit it .
 * @ param classVisitor
 * the visitor that must visit the field .
 * @ param context
 * information about the class being parsed .
 * @ param u
 * the start offset of the field in the class file .
 * @ return the offset of the first byte following the field in the class . */
private int readField ( final ClassVisitor classVisitor , final Context context , int u ) { } }

implementation:
// reads the field declaration
char [ ] c = context . buffer ; int access = readUnsignedShort ( u ) ; String name = readUTF8 ( u + 2 , c ) ; String desc = readUTF8 ( u + 4 , c ) ; u += 6 ; // reads the field attributes
String signature = null ; int anns = 0 ; int ianns = 0 ; int tanns = 0 ; int itanns = 0 ; Object value = null ; Attribute attributes = null ; for ( int i = readUnsignedShort ( u ) ; i > 0 ; -- i ) { String attrName = readUTF8 ( u + 2 , c ) ; // tests are sorted in decreasing frequency order
// ( based on frequencies observed on typical classes )
if ( "ConstantValue" . equals ( attrName ) ) { int item = readUnsignedShort ( u + 8 ) ; value = item == 0 ? null : readConst ( item , c ) ; } else if ( SIGNATURES && "Signature" . equals ( attrName ) ) { signature = readUTF8 ( u + 8 , c ) ; } else if ( "Deprecated" . equals ( attrName ) ) { access |= Opcodes . ACC_DEPRECATED ; } else if ( "Synthetic" . equals ( attrName ) ) { access |= Opcodes . ACC_SYNTHETIC | ClassWriter . ACC_SYNTHETIC_ATTRIBUTE ; } else if ( ANNOTATIONS && "RuntimeVisibleAnnotations" . equals ( attrName ) ) { anns = u + 8 ; } else if ( ANNOTATIONS && "RuntimeVisibleTypeAnnotations" . equals ( attrName ) ) { tanns = u + 8 ; } else if ( ANNOTATIONS && "RuntimeInvisibleAnnotations" . equals ( attrName ) ) { ianns = u + 8 ; } else if ( ANNOTATIONS && "RuntimeInvisibleTypeAnnotations" . equals ( attrName ) ) { itanns = u + 8 ; } else { Attribute attr = readAttribute ( context . attrs , attrName , u + 8 , readInt ( u + 4 ) , c , - 1 , null ) ; if ( attr != null ) { attr . next = attributes ; attributes = attr ; } } u += 6 + readInt ( u + 4 ) ; } u += 2 ; // visits the field declaration
FieldVisitor fv = classVisitor . visitField ( access , name , desc , signature , value ) ; if ( fv == null ) { return u ; } // visits the field annotations and type annotations
if ( ANNOTATIONS && anns != 0 ) { for ( int i = readUnsignedShort ( anns ) , v = anns + 2 ; i > 0 ; -- i ) { v = readAnnotationValues ( v + 2 , c , true , fv . visitAnnotation ( readUTF8 ( v , c ) , true ) ) ; } } if ( ANNOTATIONS && ianns != 0 ) { for ( int i = readUnsignedShort ( ianns ) , v = ianns + 2 ; i > 0 ; -- i ) { v = readAnnotationValues ( v + 2 , c , true , fv . visitAnnotation ( readUTF8 ( v , c ) , false ) ) ; } } if ( ANNOTATIONS && tanns != 0 ) { for ( int i = readUnsignedShort ( tanns ) , v = tanns + 2 ; i > 0 ; -- i ) { v = readAnnotationTarget ( context , v ) ; v = readAnnotationValues ( v + 2 , c , true , fv . visitTypeAnnotation ( context . typeRef , context . typePath , readUTF8 ( v , c ) , true ) ) ; } } if ( ANNOTATIONS && itanns != 0 ) { for ( int i = readUnsignedShort ( itanns ) , v = itanns + 2 ; i > 0 ; -- i ) { v = readAnnotationTarget ( context , v ) ; v = readAnnotationValues ( v + 2 , c , true , fv . visitTypeAnnotation ( context . typeRef , context . typePath , readUTF8 ( v , c ) , false ) ) ; } } // visits the field attributes
while ( attributes != null ) { Attribute attr = attributes . next ; attributes . next = null ; fv . visitAttribute ( attributes ) ; attributes = attr ; } // visits the end of the field
fv . visitEnd ( ) ; return u ;


signature:
public class ClassReader { /** * Reads a method and makes the given visitor visit it .
 * @ param classVisitor
 * the visitor that must visit the method .
 * @ param context
 * information about the class being parsed .
 * @ param u
 * the start offset of the method in the class file .
 * @ return the offset of the first byte following the method in the class . */
private int readMethod ( final ClassVisitor classVisitor , final Context context , int u ) { } }

implementation:
// reads the method declaration
char [ ] c = context . buffer ; context . access = readUnsignedShort ( u ) ; context . name = readUTF8 ( u + 2 , c ) ; context . desc = readUTF8 ( u + 4 , c ) ; u += 6 ; // reads the method attributes
int code = 0 ; int exception = 0 ; String [ ] exceptions = null ; String signature = null ; int methodParameters = 0 ; int anns = 0 ; int ianns = 0 ; int tanns = 0 ; int itanns = 0 ; int dann = 0 ; int mpanns = 0 ; int impanns = 0 ; int firstAttribute = u ; Attribute attributes = null ; for ( int i = readUnsignedShort ( u ) ; i > 0 ; -- i ) { String attrName = readUTF8 ( u + 2 , c ) ; // tests are sorted in decreasing frequency order
// ( based on frequencies observed on typical classes )
if ( "Code" . equals ( attrName ) ) { if ( ( context . flags & SKIP_CODE ) == 0 ) { code = u + 8 ; } } else if ( "Exceptions" . equals ( attrName ) ) { exceptions = new String [ readUnsignedShort ( u + 8 ) ] ; exception = u + 10 ; for ( int j = 0 ; j < exceptions . length ; ++ j ) { exceptions [ j ] = readClass ( exception , c ) ; exception += 2 ; } } else if ( SIGNATURES && "Signature" . equals ( attrName ) ) { signature = readUTF8 ( u + 8 , c ) ; } else if ( "Deprecated" . equals ( attrName ) ) { context . access |= Opcodes . ACC_DEPRECATED ; } else if ( ANNOTATIONS && "RuntimeVisibleAnnotations" . equals ( attrName ) ) { anns = u + 8 ; } else if ( ANNOTATIONS && "RuntimeVisibleTypeAnnotations" . equals ( attrName ) ) { tanns = u + 8 ; } else if ( ANNOTATIONS && "AnnotationDefault" . equals ( attrName ) ) { dann = u + 8 ; } else if ( "Synthetic" . equals ( attrName ) ) { context . access |= Opcodes . ACC_SYNTHETIC | ClassWriter . ACC_SYNTHETIC_ATTRIBUTE ; } else if ( ANNOTATIONS && "RuntimeInvisibleAnnotations" . equals ( attrName ) ) { ianns = u + 8 ; } else if ( ANNOTATIONS && "RuntimeInvisibleTypeAnnotations" . equals ( attrName ) ) { itanns = u + 8 ; } else if ( ANNOTATIONS && "RuntimeVisibleParameterAnnotations" . equals ( attrName ) ) { mpanns = u + 8 ; } else if ( ANNOTATIONS && "RuntimeInvisibleParameterAnnotations" . equals ( attrName ) ) { impanns = u + 8 ; } else if ( "MethodParameters" . equals ( attrName ) ) { methodParameters = u + 8 ; } else { Attribute attr = readAttribute ( context . attrs , attrName , u + 8 , readInt ( u + 4 ) , c , - 1 , null ) ; if ( attr != null ) { attr . next = attributes ; attributes = attr ; } } u += 6 + readInt ( u + 4 ) ; } u += 2 ; // visits the method declaration
MethodVisitor mv = classVisitor . visitMethod ( context . access , context . name , context . desc , signature , exceptions ) ; if ( mv == null ) { return u ; } /* * if the returned MethodVisitor is in fact a MethodWriter , it means
 * there is no method adapter between the reader and the writer . If , in
 * addition , the writer ' s constant pool was copied from this reader
 * ( mw . cw . cr = = this ) , and the signature and exceptions of the method
 * have not been changed , then it is possible to skip all visit events
 * and just copy the original code of the method to the writer ( the
 * access , name and descriptor can have been changed , this is not
 * important since they are not copied as is from the reader ) . */
if ( WRITER && mv instanceof MethodWriter ) { MethodWriter mw = ( MethodWriter ) mv ; if ( mw . cw . cr == this && signature == mw . signature ) { boolean sameExceptions = false ; if ( exceptions == null ) { sameExceptions = mw . exceptionCount == 0 ; } else if ( exceptions . length == mw . exceptionCount ) { sameExceptions = true ; for ( int j = exceptions . length - 1 ; j >= 0 ; -- j ) { exception -= 2 ; if ( mw . exceptions [ j ] != readUnsignedShort ( exception ) ) { sameExceptions = false ; break ; } } } if ( sameExceptions ) { /* * we do not copy directly the code into MethodWriter to
 * save a byte array copy operation . The real copy will be
 * done in ClassWriter . toByteArray ( ) . */
mw . classReaderOffset = firstAttribute ; mw . classReaderLength = u - firstAttribute ; return u ; } } } // visit the method parameters
if ( methodParameters != 0 ) { for ( int i = b [ methodParameters ] & 0xFF , v = methodParameters + 1 ; i > 0 ; -- i , v = v + 4 ) { mv . visitParameter ( readUTF8 ( v , c ) , readUnsignedShort ( v + 2 ) ) ; } } // visits the method annotations
if ( ANNOTATIONS && dann != 0 ) { AnnotationVisitor dv = mv . visitAnnotationDefault ( ) ; readAnnotationValue ( dann , c , null , dv ) ; if ( dv != null ) { dv . visitEnd ( ) ; } } if ( ANNOTATIONS && anns != 0 ) { for ( int i = readUnsignedShort ( anns ) , v = anns + 2 ; i > 0 ; -- i ) { v = readAnnotationValues ( v + 2 , c , true , mv . visitAnnotation ( readUTF8 ( v , c ) , true ) ) ; } } if ( ANNOTATIONS && ianns != 0 ) { for ( int i = readUnsignedShort ( ianns ) , v = ianns + 2 ; i > 0 ; -- i ) { v = readAnnotationValues ( v + 2 , c , true , mv . visitAnnotation ( readUTF8 ( v , c ) , false ) ) ; } } if ( ANNOTATIONS && tanns != 0 ) { for ( int i = readUnsignedShort ( tanns ) , v = tanns + 2 ; i > 0 ; -- i ) { v = readAnnotationTarget ( context , v ) ; v = readAnnotationValues ( v + 2 , c , true , mv . visitTypeAnnotation ( context . typeRef , context . typePath , readUTF8 ( v , c ) , true ) ) ; } } if ( ANNOTATIONS && itanns != 0 ) { for ( int i = readUnsignedShort ( itanns ) , v = itanns + 2 ; i > 0 ; -- i ) { v = readAnnotationTarget ( context , v ) ; v = readAnnotationValues ( v + 2 , c , true , mv . visitTypeAnnotation ( context . typeRef , context . typePath , readUTF8 ( v , c ) , false ) ) ; } } if ( ANNOTATIONS && mpanns != 0 ) { readParameterAnnotations ( mv , context , mpanns , true ) ; } if ( ANNOTATIONS && impanns != 0 ) { readParameterAnnotations ( mv , context , impanns , false ) ; } // visits the method attributes
while ( attributes != null ) { Attribute attr = attributes . next ; attributes . next = null ; mv . visitAttribute ( attributes ) ; attributes = attr ; } // visits the method code
if ( code != 0 ) { mv . visitCode ( ) ; readCode ( mv , context , code ) ; } // visits the end of the method
mv . visitEnd ( ) ; return u ;


signature:
public class ClassReader { /** * Computes the implicit frame of the method currently being parsed ( as
 * defined in the given { @ link Context } ) and stores it in the given context .
 * @ param frame
 * information about the class being parsed . */
private void getImplicitFrame ( final Context frame ) { } }

implementation: String desc = frame . desc ; Object [ ] locals = frame . local ; int local = 0 ; if ( ( frame . access & Opcodes . ACC_STATIC ) == 0 ) { if ( "<init>" . equals ( frame . name ) ) { locals [ local ++ ] = Opcodes . UNINITIALIZED_THIS ; } else { locals [ local ++ ] = readClass ( header + 2 , frame . buffer ) ; } } int i = 1 ; loop : while ( true ) { int j = i ; switch ( desc . charAt ( i ++ ) ) { case 'Z' : case 'C' : case 'B' : case 'S' : case 'I' : locals [ local ++ ] = Opcodes . INTEGER ; break ; case 'F' : locals [ local ++ ] = Opcodes . FLOAT ; break ; case 'J' : locals [ local ++ ] = Opcodes . LONG ; break ; case 'D' : locals [ local ++ ] = Opcodes . DOUBLE ; break ; case '[' : while ( desc . charAt ( i ) == '[' ) { ++ i ; } if ( desc . charAt ( i ) == 'L' ) { ++ i ; while ( desc . charAt ( i ) != ';' ) { ++ i ; } } locals [ local ++ ] = desc . substring ( j , ++ i ) ; break ; case 'L' : while ( desc . charAt ( i ) != ';' ) { ++ i ; } locals [ local ++ ] = desc . substring ( j + 1 , i ++ ) ; break ; default : break loop ; } } frame . localCount = local ;


signature:
public class ClassReader { /** * Reads a stack map frame and stores the result in the given
 * { @ link Context } object .
 * @ param stackMap
 * the start offset of a stack map frame in the class file .
 * @ param zip
 * if the stack map frame at stackMap is compressed or not .
 * @ param unzip
 * if the stack map frame must be uncompressed .
 * @ param frame
 * where the parsed stack map frame must be stored .
 * @ return the offset of the first byte following the parsed frame . */
private int readFrame ( int stackMap , boolean zip , boolean unzip , Context frame ) { } }

implementation:
char [ ] c = frame . buffer ; Label [ ] labels = frame . labels ; int tag ; int delta ; if ( zip ) { tag = b [ stackMap ++ ] & 0xFF ; } else { tag = MethodWriter . FULL_FRAME ; frame . offset = - 1 ; } frame . localDiff = 0 ; if ( tag < MethodWriter . SAME_LOCALS_1_STACK_ITEM_FRAME ) { delta = tag ; frame . mode = Opcodes . F_SAME ; frame . stackCount = 0 ; } else if ( tag < MethodWriter . RESERVED ) { delta = tag - MethodWriter . SAME_LOCALS_1_STACK_ITEM_FRAME ; stackMap = readFrameType ( frame . stack , 0 , stackMap , c , labels ) ; frame . mode = Opcodes . F_SAME1 ; frame . stackCount = 1 ; } else { delta = readUnsignedShort ( stackMap ) ; stackMap += 2 ; if ( tag == MethodWriter . SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED ) { stackMap = readFrameType ( frame . stack , 0 , stackMap , c , labels ) ; frame . mode = Opcodes . F_SAME1 ; frame . stackCount = 1 ; } else if ( tag >= MethodWriter . CHOP_FRAME && tag < MethodWriter . SAME_FRAME_EXTENDED ) { frame . mode = Opcodes . F_CHOP ; frame . localDiff = MethodWriter . SAME_FRAME_EXTENDED - tag ; frame . localCount -= frame . localDiff ; frame . stackCount = 0 ; } else if ( tag == MethodWriter . SAME_FRAME_EXTENDED ) { frame . mode = Opcodes . F_SAME ; frame . stackCount = 0 ; } else if ( tag < MethodWriter . FULL_FRAME ) { int local = unzip ? frame . localCount : 0 ; for ( int i = tag - MethodWriter . SAME_FRAME_EXTENDED ; i > 0 ; i -- ) { stackMap = readFrameType ( frame . local , local ++ , stackMap , c , labels ) ; } frame . mode = Opcodes . F_APPEND ; frame . localDiff = tag - MethodWriter . SAME_FRAME_EXTENDED ; frame . localCount += frame . localDiff ; frame . stackCount = 0 ; } else { // if ( tag = = FULL _ FRAME ) {
frame . mode = Opcodes . F_FULL ; int n = readUnsignedShort ( stackMap ) ; stackMap += 2 ; frame . localDiff = n ; frame . localCount = n ; for ( int local = 0 ; n > 0 ; n -- ) { stackMap = readFrameType ( frame . local , local ++ , stackMap , c , labels ) ; } n = readUnsignedShort ( stackMap ) ; stackMap += 2 ; frame . stackCount = n ; for ( int stack = 0 ; n > 0 ; n -- ) { stackMap = readFrameType ( frame . stack , stack ++ , stackMap , c , labels ) ; } } } frame . offset += delta + 1 ; readLabel ( frame . offset , labels ) ; return stackMap ;


signature:
public class ClassReader { /** * Reads a stack map frame type and stores it at the given index in the
 * given array .
 * @ param frame
 * the array where the parsed type must be stored .
 * @ param index
 * the index in ' frame ' where the parsed type must be stored .
 * @ param v
 * the start offset of the stack map frame type to read .
 * @ param buf
 * a buffer to read strings .
 * @ param labels
 * the labels of the method currently being parsed , indexed by
 * their offset . If the parsed type is an Uninitialized type , a
 * new label for the corresponding NEW instruction is stored in
 * this array if it does not already exist .
 * @ return the offset of the first byte after the parsed type . */
private int readFrameType ( final Object [ ] frame , final int index , int v , final char [ ] buf , final Label [ ] labels ) { } }

implementation:
int type = b [ v ++ ] & 0xFF ; switch ( type ) { case 0 : frame [ index ] = Opcodes . TOP ; break ; case 1 : frame [ index ] = Opcodes . INTEGER ; break ; case 2 : frame [ index ] = Opcodes . FLOAT ; break ; case 3 : frame [ index ] = Opcodes . DOUBLE ; break ; case 4 : frame [ index ] = Opcodes . LONG ; break ; case 5 : frame [ index ] = Opcodes . NULL ; break ; case 6 : frame [ index ] = Opcodes . UNINITIALIZED_THIS ; break ; case 7 : // Object
frame [ index ] = readClass ( v , buf ) ; v += 2 ; break ; default : // Uninitialized
frame [ index ] = readLabel ( readUnsignedShort ( v ) , labels ) ; v += 2 ; } return v ;


signature:
public class Tag { /** * 标题级别
 * @ return 0 表示不是标题 , 1-6 分别表示标题级别 */
public int getHeadingLevel ( ) { } }

implementation: if ( this . isElement ( ) ) { Matcher m = Pattern . compile ( "^H([1-9])$" ) . matcher ( tagName ( ) ) ; if ( m . find ( ) ) return Integer . parseInt ( m . group ( 1 ) ) ; } return 0 ;


signature:
public class Xmls { /** * 帮你快速获得一个 DocumentBuilder , 方便 XML 解析 。
 * @ return 一个 DocumentBuilder 对象
 * @ throws ParserConfigurationException */
public static DocumentBuilder xmls ( ) throws ParserConfigurationException { } }

implementation:
DocumentBuilderFactory dbf = DocumentBuilderFactory . newInstance ( ) ; String FEATURE = null ; // This is the PRIMARY defense . If DTDs ( doctypes ) are disallowed , almost all XML entity attacks are prevented
// Xerces 2 only - http : / / xerces . apache . org / xerces2 - j / features . html # disallow - doctype - decl
FEATURE = "http://apache.org/xml/features/disallow-doctype-decl" ; dbf . setFeature ( FEATURE , true ) ; // If you can ' t completely disable DTDs , then at least do the following :
// Xerces 1 - http : / / xerces . apache . org / xerces - j / features . html # external - general - entities
// Xerces 2 - http : / / xerces . apache . org / xerces2 - j / features . html # external - general - entities
// JDK7 + - http : / / xml . org / sax / features / external - general - entities
FEATURE = "http://xml.org/sax/features/external-general-entities" ; dbf . setFeature ( FEATURE , false ) ; // Xerces 1 - http : / / xerces . apache . org / xerces - j / features . html # external - parameter - entities
// Xerces 2 - http : / / xerces . apache . org / xerces2 - j / features . html # external - parameter - entities
// JDK7 + - http : / / xml . org / sax / features / external - parameter - entities
FEATURE = "http://xml.org/sax/features/external-parameter-entities" ; dbf . setFeature ( FEATURE , false ) ; // Disable external DTDs as well
FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd" ; dbf . setFeature ( FEATURE , false ) ; // and these as well , per Timothy Morgan ' s 2014 paper : " XML Schema , DTD , and Entity Attacks "
dbf . setXIncludeAware ( false ) ; dbf . setExpandEntityReferences ( false ) ; return dbf . newDocumentBuilder ( ) ;


signature:
public class Xmls { /** * 快捷的解析 XML 文件的帮助方法 , 它会主动关闭输入流
 * @ param ins
 * XML 文件输入流
 * @ return Document 对象 */
public static Document xml ( InputStream ins , Charset charset ) { } }

implementation: try { if ( charset == null ) charset = Encoding . CHARSET_UTF8 ; return xmls ( ) . parse ( new InputSource ( new InputStreamReader ( ins , charset ) ) ) ; } catch ( SAXException e ) { throw Lang . wrapThrow ( e ) ; } catch ( IOException e ) { throw Lang . wrapThrow ( e ) ; } catch ( ParserConfigurationException e ) { throw Lang . wrapThrow ( e ) ; } finally { Streams . safeClose ( ins ) ; }


signature:
public class Xmls { /** * 快捷的解析 XML 文件的帮助方法
 * @ param xmlFile
 * XML 文件
 * @ return Document 对象 */
public static Document xml ( File xmlFile , Charset charset ) { } }

implementation: InputStream ins = null ; try { ins = new FileInputStream ( xmlFile ) ; return xml ( ins , charset ) ; } catch ( Exception e ) { throw Lang . wrapThrow ( e ) ; }


signature:
public class Xmls { /** * 获取某元素下某节点的全部文本内容 ( 去掉左右空白 )
 * @ param ele
 * 元素
 * @ param subTagName
 * 子元素名
 * @ return 内容 , null 表示子元素不存在 , 空串表示元素没有对应文本内容 */
public static String get ( Element ele , String subTagName ) { } }

implementation: Element sub = firstChild ( ele , subTagName ) ; if ( null == sub ) return null ; return getText ( sub ) ;


signature:
public class Xmls { /** * 从一个 XML 元素开始 , 根据一条 XPath 获取一个元素
 * @ param ele
 * XML 元素
 * @ param xpath
 * 要获取的元素的 XPath
 * @ return 元素 , null 表示不存在 */
public static Element getEle ( Element ele , String xpath ) { } }

implementation: XPathFactory factory = XPathFactory . newInstance ( ) ; XPath xp = factory . newXPath ( ) ; try { XPathExpression expression = xp . compile ( xpath ) ; return ( Element ) expression . evaluate ( ele , XPathConstants . NODE ) ; } catch ( XPathExpressionException e ) { throw Lang . wrapThrow ( e ) ; }


signature:
public class Xmls { /** * 从某个元素里获取一个指定下标且指定名称的子元素
 * @ param ele
 * XML 元素
 * @ param index
 * 子元素下标 ( 0 base )
 * @ param regex
 * 元素名称的正则表达式
 * @ return 子元素 */
public static Element getChild ( Element ele , final int index , String regex ) { } }

implementation: final int pos = index ; final Element [ ] tag = new Element [ 1 ] ; eachChildren ( ele , null , new Each < Element > ( ) { public void invoke ( int index , Element cld , int length ) { if ( index >= pos ) { tag [ 0 ] = cld ; Lang . Break ( ) ; } } } ) ; return tag [ 0 ] ;


signature:
public class Xmls { /** * 获取 XML 元素内最后一个子元素
 * @ param ele
 * XML 元素
 * @ return 子元素 , null 表示不存在 */
public static Element lastChild ( Element ele ) { } }

implementation: final Element [ ] tag = new Element [ 1 ] ; eachChildren ( ele , null , new Each < Element > ( ) { public void invoke ( int index , Element cld , int length ) { tag [ 0 ] = cld ; Lang . Break ( ) ; } } , - 1 ) ; return tag [ 0 ] ;


signature:
public class Xmls { /** * 获取 XML 元素内名字符合一个正则表达式的元素
 * @ param ele
 * XML 元素
 * @ param regex
 * 元素名称正则表达式
 * @ return 一个子元素的列表 */
public static List < Element > children ( Element ele , String regex ) { } }

implementation: final List < Element > list = new ArrayList < Element > ( ele . getChildNodes ( ) . getLength ( ) ) ; eachChildren ( ele , regex , new Each < Element > ( ) { public void invoke ( int index , Element cld , int length ) { list . add ( cld ) ; } } ) ; return list ;


signature:
public class Xmls { /** * 迭代 XML 元素内所有子元素
 * @ param ele
 * XML 元素
 * @ param callback
 * 回调 */
public static void eachChildren ( Element ele , Each < Element > callback ) { } }

implementation: eachChildren ( ele , null , callback ) ;


signature:
public class Xmls { /** * 迭代 XML 元素内名字符合一个正则表达式的子元素
 * @ param ele
 * XML 元素
 * @ param regex
 * 元素名称正则表达式
 * @ param callback
 * 回调 */
public static void eachChildren ( Element ele , String regex , final Each < Element > callback ) { } }

implementation: Xmls . eachChildren ( ele , regex , callback , 0 ) ;


signature:
public class Xmls { /** * 判断某个元素下是否有子元素
 * @ param ele
 * 元素
 * @ param regex
 * 子元素名称的正则表达式 , 如果为 null , 则元素内如果有任意元素都会返回 false
 * @ return 是否有子元素 */
public static boolean hasChild ( Element ele , String regex ) { } }

implementation: NodeList nl = ele . getChildNodes ( ) ; int len = nl . getLength ( ) ; for ( int i = 0 ; i < len ; i ++ ) { Node nd = nl . item ( i ) ; if ( nd instanceof Element ) { if ( null == regex ) return false ; if ( Regex . match ( regex , ( ( Element ) nd ) . getTagName ( ) ) ) return true ; } } return false ;


signature:
public class Xmls { /** * 迭代 XML 元素内名字符合一个正则表达式的子元素
 * @ param ele
 * XML 元素
 * @ param regex
 * 元素名称正则表达式
 * @ param callback
 * 回调
 * @ param off
 * 偏移量 。 0 表示从第一个迭代 。 - 1 表示从最后一个迭代 。 - 2表示从倒数第二个迭代 */
public static void eachChildren ( Element ele , String regex , final Each < Element > callback , int off ) { } }

implementation:
if ( null == ele || null == callback ) return ; // 正则式
final Pattern p = null == regex ? null : Pattern . compile ( regex ) ; NodeList nl = ele . getChildNodes ( ) ; // 循环子
final int len = nl . getLength ( ) ; // 每次循环执行
Callback2 < Integer , Node > eachInvoke = new Callback2 < Integer , Node > ( ) { public void invoke ( Integer index , Node nd ) { if ( nd instanceof Element ) try { Element tag = ( Element ) nd ; if ( null == p || p . matcher ( tag . getTagName ( ) ) . find ( ) ) callback . invoke ( index , tag , len ) ; } catch ( ExitLoop e ) { throw Lang . wrapThrow ( e ) ; } catch ( ContinueLoop e ) { } catch ( LoopException e ) { throw Lang . wrapThrow ( e ) ; } } } ; try { // 负向迭代
if ( off < 0 ) { for ( int i = len + off ; i >= 0 ; i -- ) { eachInvoke . invoke ( i , nl . item ( i ) ) ; } } // 正向迭代
else { for ( int i = off ; i < len ; i ++ ) { eachInvoke . invoke ( i , nl . item ( i ) ) ; } } } catch ( ExitLoop e ) { } catch ( RuntimeException e ) { if ( e . getCause ( ) instanceof ExitLoop ) return ; else throw e ; }


signature:
public class Xmls { /** * 获取该 XML 元素内所有的属性的值 , 按照Map的形式返回
 * @ param ele
 * XML 元素
 * @ return 所有属性的值 */
public static Map < String , String > getAttrs ( Element ele ) { } }

implementation: NamedNodeMap nodeMap = ele . getAttributes ( ) ; Map < String , String > attrs = new HashMap < String , String > ( nodeMap . getLength ( ) ) ; for ( int i = 0 ; i < nodeMap . getLength ( ) ; i ++ ) { attrs . put ( nodeMap . item ( i ) . getNodeName ( ) , nodeMap . item ( i ) . getNodeValue ( ) ) ; } return attrs ;


signature:
public class Xmls { /** * 从 XML 元素中得到指定属性的值 , 如该指定属性不存在 , 则返回Null
 * @ param ele
 * XML 元素
 * @ return 该指定属性的值 */
public static String getAttr ( Element ele , String attrName ) { } }

implementation: Node node = ele . getAttributes ( ) . getNamedItem ( attrName ) ; return node != null ? node . getNodeValue ( ) : null ;


signature:
public class Xmls { /** * 将一个下面格式的 XML :
 * < pre >
 * & lt ; xml & gt ;
 * & lt ; key1 & gt ; value1 & lt ; / key1 & gt ;
 * & lt ; key2 & gt ; value2 & lt ; / key2 & gt ;
 * & lt ; / xml & gt ;
 * < / pre >
 * 转换成一个 Map
 * @ param xml
 * XML 字符串
 * @ return Map */
public static NutMap xmlToMap ( String xml ) { } }

implementation: return Xmls . asMap ( Xmls . xml ( Lang . ins ( xml ) ) . getDocumentElement ( ) ) ;


signature:
public class Xmls { /** * 从一个 XML 元素开始 , 根据一条 XPath 获取一组元素
 * @ param ele
 * XML 元素
 * @ param xpath
 * 要获取的元素的 XPath
 * @ return 元素列表 */
public static List < Element > getEles ( Element ele , String xpath ) { } }

implementation: XPathFactory factory = XPathFactory . newInstance ( ) ; XPath xp = factory . newXPath ( ) ; try { XPathExpression expression = xp . compile ( xpath ) ; NodeList nodes = ( NodeList ) expression . evaluate ( ele , XPathConstants . NODESET ) ; List < Element > list = new ArrayList < Element > ( ) ; int len = nodes . getLength ( ) ; for ( int i = 0 ; i < len ; i ++ ) { Node node = nodes . item ( i ) ; if ( node instanceof Element ) { list . add ( ( Element ) node ) ; } } return list ; } catch ( XPathExpressionException e ) { throw Lang . wrapThrow ( e ) ; }


signature:
public class RPN { /** * 根据逆波兰表达式进行计算 */
public Object calculate ( Context context , Queue < Object > rpn ) { } }

implementation: ec . setContext ( context ) ; LinkedList < Object > operand = OperatorTree ( rpn ) ; return calculate ( operand ) ;


signature:
public class RPN { /** * 计算 */
private Object calculate ( LinkedList < Object > el2 ) { } }

implementation: if ( el2 . peek ( ) instanceof Operator ) { Operator obj = ( Operator ) el2 . peek ( ) ; return obj . calculate ( ) ; } if ( el2 . peek ( ) instanceof Elobj ) { return ( ( Elobj ) el2 . peek ( ) ) . fetchVal ( ) ; } return el2 . peek ( ) ;


signature:
public class RPN { /** * 转换成操作树 */
private LinkedList < Object > OperatorTree ( Queue < Object > rpn ) { } }

implementation: LinkedList < Object > operand = new LinkedList < Object > ( ) ; while ( ! rpn . isEmpty ( ) ) { if ( rpn . peek ( ) instanceof Operator ) { Operator opt = ( Operator ) rpn . poll ( ) ; opt . wrap ( operand ) ; operand . addFirst ( opt ) ; continue ; } if ( rpn . peek ( ) instanceof Elobj ) { ( ( Elobj ) rpn . peek ( ) ) . setEc ( ec ) ; } operand . addFirst ( rpn . poll ( ) ) ; } return operand ;


signature:
public class QueryResult { /** * 按特定泛型获取结果集 , 属于直接强转 , 不带转换
 * @ param eleType 泛型
 * @ return 结果集 */
@ SuppressWarnings ( "unchecked" ) public < T > List < T > getList ( Class < T > eleType ) { } }

implementation: return ( List < T > ) list ;


signature:
public class QueryResult { /** * 转换为特定类型的结果集
 * @ param eleType 新的结果集
 * @ return 特定类型的结果集 */
@ SuppressWarnings ( "unchecked" ) public < T > List < T > convertList ( Class < T > eleType ) { } }

implementation: if ( null == list || list . isEmpty ( ) ) return ( List < T > ) list ; List < T > re = new ArrayList < T > ( list . size ( ) ) ; Castors castors = Castors . me ( ) ; for ( Object obj : list ) re . add ( castors . castTo ( obj , eleType ) ) ; return re ;


signature:
public class ObjectNaviNode { /** * 初始化当前结点 */
public void put ( String path , String [ ] value ) { } }

implementation: StringBuilder sb = new StringBuilder ( ) ; char [ ] chars = path . toCharArray ( ) ; OUT : for ( int i = 0 ; i < chars . length ; i ++ ) { char c = chars [ i ] ; switch ( c ) { case '[' : case '(' : i ++ ; StringBuilder sb2 = new StringBuilder ( ) ; boolean isNumber = true ; for ( ; i < chars . length ; i ++ ) { char c2 = chars [ i ] ; switch ( c2 ) { case ']' : case ')' : if ( ( c == '[' && c2 == ']' ) || ( c == '(' && c2 == ')' ) ) { if ( isNumber && ! ( c == '(' ) ) { sb . append ( ':' ) . append ( sb2 ) ; } else { sb . append ( '.' ) . append ( sb2 ) ; } continue OUT ; } } isNumber = isNumber && Character . isDigit ( c2 ) ; sb2 . append ( c2 ) ; } break ; default : sb . append ( c ) ; break ; } } path = sb . toString ( ) ; putPath ( path , value ) ;


signature:
public class ObjectNaviNode { /** * 添加子结点 */
private void addChild ( String path , String [ ] value ) { } }

implementation: String subname = fetchName ( path ) ; ObjectNaviNode onn = child . get ( subname ) ; if ( onn == null ) { onn = new ObjectNaviNode ( ) ; } onn . putPath ( path , value ) ; child . put ( subname , onn ) ;


signature:
public class ObjectNaviNode { /** * 初始化name , type信息
 * @ param path */
private void init ( String path ) { } }

implementation: String key = fetchNode ( path ) ; if ( isList ( key ) ) { type = TYPE_LIST ; name = key . substring ( 0 , key . indexOf ( LIST_SEPARATOR ) ) ; return ; } name = key ;


signature:
public class ObjectNaviNode { /** * 提取子路径
 * @ param path */
private String fetchSubPath ( String path ) { } }

implementation: if ( isList ( fetchNode ( path ) ) ) { return path . substring ( path . indexOf ( LIST_SEPARATOR ) + 1 ) ; } return path . substring ( path . indexOf ( separator ) + 1 ) ;


signature:
public class ObjectNaviNode { /** * 取得节点名 */
private static String fetchNode ( String path ) { } }

implementation: if ( path . indexOf ( separator ) <= 0 ) { return path ; } return path . substring ( 0 , path . indexOf ( separator ) ) ;


signature:
public class ObjectNaviNode { /** * 取得节点的name信息 */
private String fetchName ( String path ) { } }

implementation: String key = fetchNode ( path ) ; if ( isList ( key ) ) { return key . substring ( 0 , key . indexOf ( LIST_SEPARATOR ) ) ; } return key ;


signature:
public class ObjectNaviNode { /** * 提取出list , map结构 */
@ SuppressWarnings ( { } }

implementation:
"rawtypes" , "unchecked" } ) public Object get ( ) { if ( isLeaf ( ) ) { return value == null ? null : value . length == 1 ? value [ 0 ] : value ; } if ( type == TYPE_LIST ) { // fix issue # 1109 , 列表的key需要重排
List list = new ArrayList ( ) ; List < Integer > keys = new ArrayList < Integer > ( ) ; List < String > keys2 = new ArrayList < String > ( ) ; for ( String key : child . keySet ( ) ) { try { keys . add ( Integer . parseInt ( key ) ) ; } catch ( NumberFormatException e ) { keys2 . add ( key ) ; } } Collections . sort ( keys ) ; for ( Integer index : keys ) { list . add ( child . get ( index . toString ( ) ) . get ( ) ) ; } for ( String key2 : keys2 ) { list . add ( child . get ( key2 ) . get ( ) ) ; } return list ; } Map map = new HashMap ( ) ; for ( String o : child . keySet ( ) ) { map . put ( o , child . get ( o ) . get ( ) ) ; } return map ;


signature:
public class Disks { /** * 一个 Vistor 模式的目录深层遍历
 * @ param f
 * 要遍历的目录或者文件 , 如果是目录 , 深层遍历 , 否则 , 只访问一次文件
 * @ param fv
 * 对文件要进行的操作
 * @ param filter
 * 遍历目录时 , 哪些文件应该被忽略
 * @ return 遍历的文件个数 */
public static int visitFile ( File f , FileVisitor fv , FileFilter filter ) { } }

implementation: int re = 0 ; if ( f . isFile ( ) ) { fv . visit ( f ) ; re ++ ; } else if ( f . isDirectory ( ) ) { File [ ] fs = null == filter ? f . listFiles ( ) : f . listFiles ( filter ) ; if ( fs != null ) for ( File theFile : fs ) re += visitFile ( theFile , fv , filter ) ; } return re ;


signature:
public class Disks { /** * 将两个文件对象比较 , 得出相对路径
 * @ param base
 * 基础文件对象
 * @ param file
 * 相对文件对象
 * @ return 相对于基础文件对象的相对路径 */
public static String getRelativePath ( File base , File file ) { } }

implementation: String pathBase = base . getAbsolutePath ( ) ; if ( base . isDirectory ( ) ) pathBase += "/" ; String pathFile = file . getAbsolutePath ( ) ; if ( file . isDirectory ( ) ) pathFile += "/" ; return getRelativePath ( pathBase , pathFile ) ;


signature:
public class Disks { /** * 将两个路径比较 , 得出相对路径
 * @ param base
 * 基础路径 , 以 ' / ' 结束 , 表示目录
 * @ param path
 * 相对文件路径 , 以 ' / ' 结束 , 表示目录
 * @ param equalPath
 * 如果两个路径相等 , 返回什么 , 通常为 " . / " 。 你也可以用 " " 或者 " . " 或者随便什么字符串来表示
 * @ return 相对于基础路径对象的相对路径 */
public static String getRelativePath ( String base , String path , String equalPath ) { } }

implementation:
// 如果两个路径相等
if ( base . equals ( path ) || "./" . equals ( path ) || "." . equals ( path ) ) { return equalPath ; } // 开始判断
String [ ] bb = Strings . splitIgnoreBlank ( getCanonicalPath ( base ) , "[\\\\/]" ) ; String [ ] ff = Strings . splitIgnoreBlank ( getCanonicalPath ( path ) , "[\\\\/]" ) ; int len = Math . min ( bb . length , ff . length ) ; int pos = 0 ; for ( ; pos < len ; pos ++ ) if ( ! bb [ pos ] . equals ( ff [ pos ] ) ) break ; // 证明路径是相等的
if ( len == pos && bb . length == ff . length ) { return equalPath ; } // 开始查找不同
int dir = 1 ; if ( base . endsWith ( "/" ) ) dir = 0 ; StringBuilder sb = new StringBuilder ( Strings . dup ( "../" , bb . length - pos - dir ) ) ; sb . append ( Lang . concat ( pos , ff . length - pos , '/' , ff ) ) ; if ( path . endsWith ( "/" ) ) sb . append ( '/' ) ; return sb . toString ( ) ;


signature:
public class Disks { /** * 获取两个路径从头部开始计算的交集
 * @ param ph0
 * 路径1
 * @ param ph1
 * 路径2
 * @ param dft
 * 如果两个路径完全没有相交 , 那么返回什么
 * @ return 两个路径的交集 */
public static String getIntersectPath ( String ph0 , String ph1 , String dft ) { } }

implementation:
// 木可能有交集
if ( null == ph0 || null == ph1 ) return dft ; String [ ] ss0 = Strings . splitIgnoreBlank ( ph0 , "[\\\\/]" ) ; String [ ] ss1 = Strings . splitIgnoreBlank ( ph1 , "[\\\\/]" ) ; int pos = 0 ; int len = Math . min ( ss0 . length , ss1 . length ) ; for ( ; pos < len ; pos ++ ) { if ( ! ss0 [ pos ] . equals ( ss1 [ pos ] ) ) break ; } // 木有交集
if ( pos == 0 ) return dft ; // 得到
String re = Lang . concat ( 0 , pos , "/" , ss0 ) . toString ( ) ; // 需要补全后面的 " / " 吗
if ( ph0 . endsWith ( "/" ) && ph1 . endsWith ( "/" ) ) return re + "/" ; return re ;


signature:
public class Disks { /** * 整理路径 。 将会合并路径中的 " . . "
 * @ param path
 * 路径
 * @ return 整理后的路径 */
public static String getCanonicalPath ( String path ) { } }

implementation:
if ( Strings . isBlank ( path ) ) return path ; String [ ] pa = Strings . splitIgnoreBlank ( path , "[\\\\/]" ) ; LinkedList < String > paths = new LinkedList < String > ( ) ; for ( String s : pa ) { if ( ".." . equals ( s ) ) { if ( paths . size ( ) > 0 ) paths . removeLast ( ) ; continue ; } if ( "." . equals ( s ) ) { // pass
} else { paths . add ( s ) ; } } StringBuilder sb = Lang . concat ( "/" , paths ) ; if ( path . startsWith ( "/" ) ) sb . insert ( 0 , '/' ) ; if ( path . endsWith ( "/" ) ) sb . append ( '/' ) ; return sb . toString ( ) ;


signature:
public class Disks { /** * 获取一个路径的绝对路径 。 如果该路径不存在 , 则返回null
 * @ param path
 * 路径
 * @ return 绝对路径 */
public static String absolute ( String path ) { } }

implementation: return absolute ( path , ClassTools . getClassLoader ( ) , Encoding . defaultEncoding ( ) ) ;


signature:
public class Disks { /** * 获取一个路径的绝对路径 。 如果该路径不存在 , 则返回null
 * @ param path
 * 路径
 * @ param klassLoader
 * 参考 ClassLoader
 * @ param enc
 * 路径编码方式
 * @ return 绝对路径 */
public static String absolute ( String path , ClassLoader klassLoader , String enc ) { } }

implementation:
path = normalize ( path , enc ) ; if ( Strings . isEmpty ( path ) ) return null ; File f = new File ( path ) ; if ( ! f . exists ( ) ) { URL url = null ; try { url = klassLoader . getResource ( path ) ; if ( null == url ) url = Thread . currentThread ( ) . getContextClassLoader ( ) . getResource ( path ) ; if ( null == url ) url = ClassLoader . getSystemResource ( path ) ; } catch ( Throwable e ) { } if ( null != url ) return normalize ( url . getPath ( ) , Encoding . UTF8 ) ; // 通过URL获取String , 一律使用UTF - 8编码进行解码
return null ; } return path ;


signature:
public class Disks { /** * 让路径变成正常路径 , 将 ~ 替换成用户主目录
 * @ param path
 * 路径
 * @ param enc
 * 路径编码方式
 * @ return 正常化后的路径 */
public static String normalize ( String path , String enc ) { } }

implementation: if ( Strings . isEmpty ( path ) ) return null ; if ( path . charAt ( 0 ) == '~' ) path = Disks . home ( ) + path . substring ( 1 ) ; try { return URLDecoder . decode ( path , enc ) ; } catch ( UnsupportedEncodingException e ) { return null ; }


signature:
public class Disks { /** * 遍历文件夹下以特定后缀结尾的文件 ( 不包括文件夹 , 不包括 . 开头的文件 )
 * @ param path
 * 根路径
 * @ param regex
 * 文件名的正则表达式
 * @ param deep
 * 是否深层遍历
 * @ param fv
 * 你所提供的访问器 , 当然就是你自己的逻辑咯 */
public static final void visitFile ( String path , final String regex , final boolean deep , final FileVisitor fv ) { } }

implementation: File d = Files . findFile ( path ) ; if ( null == d ) return ; visitFile ( d , new FileVisitor ( ) { @ Override public void visit ( File f ) { if ( f . isDirectory ( ) ) return ; fv . visit ( f ) ; } } , new FileFilter ( ) { @ Override public boolean accept ( File f ) { if ( f . isDirectory ( ) ) return deep ; if ( f . isHidden ( ) ) return false ; if ( Strings . isEmpty ( regex ) ) return true ; return Regex . match ( regex , f . getName ( ) ) ; } } ) ;


signature:
public class Disks { /** * 将多个路径拼合成一个路径 , 他会自动去除重复的 " / "
 * < pre >
 * appendPath ( " a " , " b " ) = > " a / b "
 * appendPath ( " / a " , " b / c " ) = > " / a / b / c "
 * appendPath ( " / a / " , " / b / c " ) = > " / a / b / c "
 * < / pre >
 * @ param phs
 * 路径数组
 * @ return 拼合后的路径 */
public static String appendPath ( String ... phs ) { } }

implementation:
String [ ] paths = Lang . without ( phs , null ) ; if ( null != paths && paths . length > 0 ) { // zozoh : 嗯下面的逻辑木有必要了吧
// if ( null = = paths [ 0 ] )
// paths [ 0 ] = " / " ;
String str = Lang . concat ( "/" , paths ) . toString ( ) ; String [ ] ss = Strings . splitIgnoreBlank ( str , "/" ) ; str = Lang . concat ( "/" , ss ) . toString ( ) ; if ( paths [ 0 ] . startsWith ( "/" ) ) { return "/" + str ; } return str ; } return null ;


signature:
public class DaoInterceptorChain { /** * 继续下一个拦截器 , 如果已经是最后一个拦截器 , 那么执行executor . exec
 * @ return 本对象 , 用于链式操作
 * @ throws Exception */
public DaoInterceptorChain doChain ( ) throws DaoException { } }

implementation: if ( hasNext ( ) ) { DaoInterceptor interceptor = next ( ) ; current ++ ; interceptor . filter ( this ) ; } else { executor . exec ( getConnection ( ) , getDaoStatement ( ) ) ; updateCount += getDaoStatement ( ) . getUpdateCount ( ) ; } return this ;


signature:
public class DaoInterceptorChain { /** * 这是DaoExecutor会执行的方法 , 拦截器内不要执行这个方法 ! ! 这里也是拦截器开始生效的地方 . */
public void invoke ( Connection conn ) throws Exception { } }

implementation: for ( DaoStatement st : sts ) { if ( st == null ) { if ( log . isInfoEnabled ( ) ) log . info ( "Found a null DaoStatement(SQL), ingore it ~~" ) ; continue ; } current = 0 ; daoStatement = st ; this . connection = conn ; doChain ( ) ; }


signature:
public class Record { /** * 根据 ResultSet 创建一个记录对象
 * @ param rs ResultSet 对象
 * @ return 记录对象 */
public static Record create ( ResultSet rs ) { } }

implementation: Record re = create ( ) ; create ( re , rs , null ) ; return re ;


signature:
public class Record { /** * 移除一个字段
 * @ param name 字段名
 * @ return 移除的字段值 */
public Object remove ( String name ) { } }

implementation: keys . remove ( name ) ; return map . remove ( name . toLowerCase ( ) ) ;


signature:
public class Record { /** * 返回指定字段的 String 值
 * 如果该字段在记录中不存在 , 返回 null
 * @ param name 字段名
 * @ return 指定字段的 String 值 。 如果该字段在记录中不存在 , 返回 null */
public String getString ( String name ) { } }

implementation: Object val = get ( name ) ; if ( null == val ) return null ; return Castors . me ( ) . castToString ( val ) ;


signature:
public class Record { /** * 返回指定字段的 Blob 值
 * 如果该字段在记录中不存在 , 返回 null
 * @ param name 字段名
 * @ return 指定字段的 Blob 值 。 如果该字段在记录中不存在 , 返回 null */
public Blob getBlob ( String name ) { } }

implementation: Object val = get ( name ) ; if ( null == val ) return null ; return Castors . me ( ) . castTo ( val , Blob . class ) ;


signature:
public class Record { /** * 返回指定字段的 Timestamp 值
 * 如果该字段在记录中不存在 , 返回 null
 * @ param name 字段名
 * @ return 指定字段的 Timestamp 值 。 如果该字段在记录中不存在 , 返回 null */
public Timestamp getTimestamp ( String name ) { } }

implementation: Object val = get ( name ) ; if ( null == val ) return null ; return Castors . me ( ) . castTo ( val , Timestamp . class ) ;


signature:
public class Record { /** * 返回指定字段的值
 * 如果该字段在记录中不存在 , 返回 null
 * @ param name 字段名
 * @ return 指定字段的值 。 如果该字段在记录中不存在 , 返回 null */
public Object get ( Object name ) { } }

implementation: if ( null == name ) return null ; return map . get ( name . toString ( ) . toLowerCase ( ) ) ;


signature:
public class Record { /** * 将字段与其对应的值放入该记录中
 * @ param name 字段名
 * @ param value 字段值
 * @ return 该字段之前所对应的值 ; 如果之前该字段在该记录中不存在 , 则返回 null */
public Object put ( String name , Object value ) { } }

implementation: keys . add ( name ) ; return map . put ( name . toLowerCase ( ) , value ) ;


signature:
public class ChainParsing { /** * 对象在参数中 , 是否后续获取属性或调用方法 */
private boolean hasFieldOrFunction ( ) { } }

implementation: int dot = 0 , comma = 0 ; for ( int currentIndex = i ; currentIndex < cs . length ; currentIndex ++ ) { char c = cs [ currentIndex ] ; if ( c == '.' ) dot = currentIndex ; if ( c == ',' ) comma = currentIndex ; } return dot < comma || ( dot != 0 && comma == 0 ) ; // 点号在逗号前边或后边有点号没有逗号


signature:
public class Times { /** * 将一个秒数 ( 天中 ) , 转换成一个如下格式的数组 :
 * < pre >
 * [ 0-23 ] [ 0-59 [ - 059]
 * < / pre >
 * @ param sec
 * 秒数
 * @ return 时分秒的数组 */
public static int [ ] T ( int sec ) { } }

implementation: TmInfo ti = Ti ( sec ) ; return Nums . array ( ti . hour , ti . minute , ti . second ) ;


signature:
public class Times { /** * 将一个秒数 ( 天中 ) , 转换成一个时间对象 :
 * @ param sec
 * 秒数
 * @ return 时间对象 */
public static TmInfo Ti ( int sec ) { } }

implementation: TmInfo ti = new TmInfo ( ) ; ti . valueInMillisecond = sec * 1000 ; ti . __recound_by_valueInMilliSecond ( ) ; return ti ;


signature:
public class Times { /** * 将一个毫秒数 ( 天中 ) , 转换成一个时间对象 :
 * @ param ams
 * 毫秒数
 * @ return 时间对象 */
public static TmInfo Tims ( long ams ) { } }

implementation: TmInfo ti = new TmInfo ( ) ; ti . valueInMillisecond = ( int ) ams ; ti . __recound_by_valueInMilliSecond ( ) ; return ti ;


signature:
public class Times { /** * 将一个时间字符串 , 转换成一个一天中的绝对时间对象
 * @ param ts
 * 时间字符串 , 符合格式
 * < ul >
 * < li > " HH : mm : ss "
 * < li > " HH : mm "
 * < li > " HH : mm : ss . SSS "
 * < li > " HH : mm : ss , SSS "
 * < / ul >
 * @ return 时间对象 */
public static TmInfo Ti ( String ts ) { } }

implementation:
Matcher m = _p_tm . matcher ( ts ) ; if ( m . find ( ) ) { TmInfo ti = new TmInfo ( ) ; // 仅仅到分钟
if ( null == m . group ( 3 ) ) { ti . hour = Integer . parseInt ( m . group ( 1 ) ) ; ti . minute = Integer . parseInt ( m . group ( 2 ) ) ; ti . second = 0 ; ti . millisecond = 0 ; } // 到秒
else if ( null == m . group ( 5 ) ) { ti . hour = Integer . parseInt ( m . group ( 1 ) ) ; ti . minute = Integer . parseInt ( m . group ( 2 ) ) ; ti . second = Integer . parseInt ( m . group ( 4 ) ) ; ti . millisecond = 0 ; } // 到毫秒
else { ti . hour = Integer . parseInt ( m . group ( 1 ) ) ; ti . minute = Integer . parseInt ( m . group ( 2 ) ) ; ti . second = Integer . parseInt ( m . group ( 4 ) ) ; ti . millisecond = Integer . parseInt ( m . group ( 6 ) ) ; } // 计算其他的值
ti . value = ti . hour * 3600 + ti . minute * 60 + ti . second ; ti . valueInMillisecond = ti . value * 1000 + ti . millisecond ; // 返回
return ti ; } throw Lang . makeThrow ( "Wrong format of time string '%s'" , ts ) ;


signature:
public class Times { /** * 根据字符串得到相对于 " UTC 1970-01-01 00:00:00 " 的绝对毫秒数 。
 * 本函数假想给定的时间字符串是本地时间 。 所以计算出来结果后 , 还需要减去时差
 * 支持的时间格式字符串为 :
 * < pre >
 * yyyy - MM - dd HH : mm : ss
 * yyyy - MM - dd HH : mm : ss . SSS
 * yy - MM - dd HH : mm : ss ;
 * yy - MM - dd HH : mm : ss . SSS ;
 * yyyy - MM - dd ;
 * yy - MM - dd ;
 * HH : mm : ss ;
 * HH : mm : ss . SSS ;
 * < / pre >
 * 时间字符串后面可以跟 + 8 或者 + 8:00 表示 GMT + 8:00 时区 。 同理 - 9 或者 - 9:00 表示 GMT - 9:00 时区
 * @ param ds
 * 时间字符串
 * @ param tz
 * 你给定的时间字符串是属于哪个时区的
 * @ return 时间
 * @ see # _ P _ TIME */
public static long ams ( String ds , TimeZone tz ) { } }

implementation:
Matcher m = _P_TIME . matcher ( ds ) ; if ( m . find ( ) ) { int yy = _int ( m , 2 , 1970 ) ; int MM = _int ( m , 4 , 1 ) ; int dd = _int ( m , 6 , 1 ) ; int HH = _int ( m , 9 , 0 ) ; int mm = _int ( m , 11 , 0 ) ; int ss = _int ( m , 14 , 0 ) ; int ms = _int ( m , 17 , 0 ) ; /* * zozoh : 先干掉 , 还是用 SimpleDateFormat 吧 , " 1980-05-01 15:17:23 " 之前的日子
 * 得出的时间竟然总是多 30 分钟 long day = ( long ) D1970 ( yy , MM , dd ) ; long MS =
 * day * 86400000L ; MS + = ( ( ( long ) HH ) * 3600L + ( ( long ) mm ) * 60L +
 * ss ) * 1000L ; MS + = ( long ) ms ;
 * / / 如果没有指定时区 . . . if ( null = = tz ) { / / 那么用字符串中带有的时区信息 , if
 * ( ! Strings . isBlank ( m . group ( 17 ) ) ) { tz =
 * TimeZone . getTimeZone ( String . format ( " GMT % s % s : 00 " , m . group ( 18 ) ,
 * m . group ( 19 ) ) ) ; / / tzOffset = Long . parseLong ( m . group ( 19 ) ) / / *
 * 3600000L / / * ( m . group ( 18 ) . charAt ( 0 ) = = ' - ' ? - 1 : 1 ) ;
 * } / / 如果依然木有 , 则用系统默认时区 else { tz = TimeZone . getDefault ( ) ; } }
 * / / 计算 return MS - tz . getRawOffset ( ) - tz . getDSTSavings ( ) ; */
String str = String . format ( "%04d-%02d-%02d %02d:%02d:%02d.%03d" , yy , MM , dd , HH , mm , ss , ms ) ; SimpleDateFormat df = ( SimpleDateFormat ) DF_DATE_TIME_MS4 . clone ( ) ; // 那么用字符串中带有的时区信息 . . .
if ( null == tz && ! Strings . isBlank ( m . group ( 18 ) ) ) { tz = TimeZone . getTimeZone ( String . format ( "GMT%s%s:00" , m . group ( 19 ) , m . group ( 20 ) ) ) ; } // 指定时区 . . .
if ( null != tz ) df . setTimeZone ( tz ) ; // 解析返回
try { return df . parse ( str ) . getTime ( ) ; } catch ( ParseException e ) { throw Lang . wrapThrow ( e ) ; } } else if ( _P_TIME_LONG . matcher ( ds ) . find ( ) ) { if ( ds . endsWith ( "L" ) ) ds . substring ( 0 , ds . length ( ) - 1 ) ; return Long . parseLong ( ds ) ; } throw Lang . makeThrow ( "Unexpect date format '%s'" , ds ) ;


signature:
public class Times { /** * 返回时间对象在一天中的毫秒数
 * @ param c
 * 时间对象
 * @ return 时间对象在一天中的毫秒数 */
public static int ms ( Calendar c ) { } }

implementation: int ms = c . get ( Calendar . HOUR_OF_DAY ) * 3600000 ; ms += c . get ( Calendar . MINUTE ) * 60000 ; ms += c . get ( Calendar . SECOND ) * 1000 ; ms += c . get ( Calendar . MILLISECOND ) ; return ms ;


signature:
public class Times { /** * 根据一个当天的绝对毫秒数 , 得到一个时间字符串 , 格式为 " HH : mm : ss . EEE "
 * @ param ms
 * 当天的绝对毫秒数
 * @ return 时间字符串 */
public static String mss ( int ms ) { } }

implementation: int sec = ms / 1000 ; ms = ms - sec * 1000 ; return secs ( sec ) + "." + Strings . alignRight ( ms , 3 , '0' ) ;


signature:
public class Times { /** * 根据一个当天的绝对秒数 , 得到一个时间字符串 , 格式为 " HH : mm : ss "
 * @ param sec
 * 当天的绝对秒数
 * @ return 时间字符串 */
public static String secs ( int sec ) { } }

implementation: int hh = sec / 3600 ; sec -= hh * 3600 ; int mm = sec / 60 ; sec -= mm * 60 ; return Strings . alignRight ( hh , 2 , '0' ) + ":" + Strings . alignRight ( mm , 2 , '0' ) + ":" + Strings . alignRight ( sec , 2 , '0' ) ;


signature:
public class Times { /** * 返回时间对象在一天中的秒数
 * @ param d
 * 时间对象
 * @ return 时间对象在一天中的秒数 */
public static int sec ( Date d ) { } }

implementation: Calendar c = C ( d ) ; int sec = c . get ( Calendar . HOUR_OF_DAY ) * 3600 ; sec += c . get ( Calendar . MINUTE ) * 60 ; sec += c . get ( Calendar . SECOND ) ; return sec ;


signature:
public class Times { /** * 计算一个给定日期 , 距离 1970 年 1 月 1 日有多少天
 * @ param yy
 * 年 , 比如 1999 , 或者 43
 * @ param MM
 * 月 , 一月为 1 , 十二月为 12
 * @ param dd
 * 日 , 每月一号为 1
 * @ return 距离 1970 年 1 月 1 日的天数 */
public static int D1970 ( int yy , int MM , int dd ) { } }

implementation:
// 转换成相对公元元年的年份
// 如果给的年份小于 100 , 那么就认为是从 1970 开始算的年份
int year = ( yy < 100 ? yy + 1970 : yy ) ; // 得到今年之前的基本天数
int day = ( year - 1970 ) * 365 ; // 补上闰年天数
day += countLeapYear ( year ) - countLeapYear ( 1970 ) ; // 计算今年本月之前的月份
int mi = Math . min ( MM - 1 , 11 ) ; boolean isLeapYear = leapYear ( yy ) ; for ( int i = 0 ; i < mi ; i ++ ) { day += _MDs [ i ] ; } // 考虑今年是闰年的情况
if ( isLeapYear && MM > 2 ) { day ++ ; } // 最后加上天数
day += Math . min ( dd , _MDs [ mi ] ) - 1 ; // 如果是闰年且本月是 2 月
if ( isLeapYear && dd == 29 ) { day ++ ; } // 如果是闰年并且过了二月
return day ;


signature:
public class Times { /** * 根据毫秒数得到时间
 * @ param ms
 * 时间的毫秒数
 * @ return 时间 */
public static Calendar C ( long ms ) { } }

implementation: Calendar c = Calendar . getInstance ( ) ; c . setTimeInMillis ( ms ) ; return c ;


signature:
public class Times { /** * 将一个秒数 ( 天中 ) , 转换成一个格式为 HH : mm : ss 的字符串
 * @ param sec
 * 秒数
 * @ return 格式为 HH : mm : ss 的字符串 */
public static String sT ( int sec ) { } }

implementation: int [ ] ss = T ( sec ) ; return Strings . alignRight ( ss [ 0 ] , 2 , '0' ) + ":" + Strings . alignRight ( ss [ 1 ] , 2 , '0' ) + ":" + Strings . alignRight ( ss [ 2 ] , 2 , '0' ) ;


signature:
public class Times { /** * 将一个秒数 ( 天中 ) , 转换成一个格式为 HH : mm 的字符串 ( 精确到分钟 )
 * @ param sec
 * 秒数
 * @ return 格式为 HH : mm 的字符串 */
public static String sTmin ( int sec ) { } }

implementation: int [ ] ss = T ( sec ) ; return Strings . alignRight ( ss [ 0 ] , 2 , '0' ) + ":" + Strings . alignRight ( ss [ 1 ] , 2 , '0' ) ;


signature:
public class Times { /** * 按周获得某几周周一 00:00:00 到周六 的时间范围
 * 它会根据给定的 offL 和 offR 得到一个时间范围
 * 对本函数来说 week ( - 3 , - 5 ) 和 week ( - 5 , - 3 ) 是一个意思
 * @ param base
 * 基础时间 , 毫秒
 * @ param offL
 * 从本周偏移几周 , 0 表示本周 , - 1 表示上一周 , 1 表示下一周
 * @ param offR
 * 从本周偏移几周 , 0 表示本周 , - 1 表示上一周 , 1 表示下一周
 * @ return 时间范围 ( 毫秒级别 ) */
public static Date [ ] weeks ( long base , int offL , int offR ) { } }

implementation:
int from = Math . min ( offL , offR ) ; int len = Math . abs ( offL - offR ) ; // 现在
Calendar c = Calendar . getInstance ( ) ; c . setTimeInMillis ( base ) ; Date [ ] re = new Date [ 2 ] ; // 计算开始
c . add ( Calendar . DAY_OF_YEAR , 7 * from ) ; c . set ( Calendar . DAY_OF_WEEK , Calendar . MONDAY ) ; c . set ( Calendar . HOUR_OF_DAY , 0 ) ; c . set ( Calendar . MINUTE , 0 ) ; c . set ( Calendar . SECOND , 0 ) ; c . set ( Calendar . MILLISECOND , 0 ) ; re [ 0 ] = c . getTime ( ) ; // 计算结束
c . add ( Calendar . DAY_OF_YEAR , 7 * ( len + 1 ) ) ; c . add ( Calendar . MILLISECOND , - 1 ) ; re [ 1 ] = c . getTime ( ) ; // 返回
return re ;


signature:
public class Times { /** * 将一个时间格式化成容易被人类阅读的格式
 * < pre >
 * 如果 1 分钟内 , 打印 Just Now
 * 如果 1 小时内 , 打印多少分钟
 * 如果 1 天之内 , 打印多少小时之前
 * 如果是今年之内 , 打印月份和日期
 * 否则打印月份和年
 * < / pre >
 * @ param d
 * @ return 日期字符串 */
public static String formatForRead ( Date d ) { } }

implementation:
long ms = System . currentTimeMillis ( ) - d . getTime ( ) ; // 如果 1 分钟内 , 打印 Just Now
if ( ms < ( 60000 ) ) { return "Just Now" ; } // 如果 1 小时内 , 打印多少分钟
if ( ms < ( 60 * 60000 ) ) { return "" + ( ms / 60000 ) + "Min." ; } // 如果 1 天之内 , 打印多少小时之前
if ( ms < ( 24 * 3600 * 1000 ) ) { return "" + ( ms / 3600000 ) + "hr." ; } // 如果一周之内 , 打印多少天之前
if ( ms < ( 7 * 24 * 3600 * 1000 ) ) { return "" + ( ms / ( 24 * 3600000 ) ) + "Day" ; } // 如果是今年之内 , 打印月份和日期
Calendar c = Calendar . getInstance ( ) ; int thisYear = c . get ( Calendar . YEAR ) ; c . setTime ( d ) ; int yy = c . get ( Calendar . YEAR ) ; int mm = c . get ( Calendar . MONTH ) ; if ( thisYear == yy ) { int dd = c . get ( Calendar . DAY_OF_MONTH ) ; return String . format ( "%s %d" , _MMM [ mm ] , dd ) ; } // 否则打印月份和年
return String . format ( "%s %d" , _MMM [ mm ] , yy ) ;


signature:
public class Times { /** * 以给定的时间格式来安全的对时间进行格式化 , 并返回格式化后所对应的字符串
 * @ param fmt
 * 时间格式
 * @ param d
 * 时间对象
 * @ return 格式化后的字符串 */
public static String format ( DateFormat fmt , Date d ) { } }

implementation: return ( ( DateFormat ) fmt . clone ( ) ) . format ( d ) ;


signature:
public class Times { /** * 以给定的时间格式来安全的对时间进行格式化 , 并返回格式化后所对应的字符串
 * @ param fmt
 * 时间格式
 * @ param d
 * 时间对象
 * @ return 格式化后的字符串 */
public static String format ( String fmt , Date d ) { } }

implementation: return new SimpleDateFormat ( fmt , Locale . ENGLISH ) . format ( d ) ;


signature:
public class Times { /** * 以给定的时间格式来安全的解析时间字符串 , 并返回解析后所对应的时间对象 ( 包裹RuntimeException )
 * @ param fmt
 * 时间格式
 * @ param s
 * 时间字符串
 * @ return 该时间字符串对应的时间对象 */
public static Date parseq ( DateFormat fmt , String s ) { } }

implementation: try { return parse ( fmt , s ) ; } catch ( ParseException e ) { throw Lang . wrapThrow ( e ) ; }


signature:
public class Times { /** * 以给定的时间格式来安全的解析时间字符串 , 并返回解析后所对应的时间对象
 * @ param fmt
 * 时间格式
 * @ param s
 * 日期时间字符串
 * @ return 该时间字符串对应的时间对象 */
public static Date parse ( DateFormat fmt , String s ) throws ParseException { } }

implementation: return ( ( DateFormat ) fmt . clone ( ) ) . parse ( s ) ;


signature:
public class Times { /** * 以给定的时间格式来安全的解析时间字符串 , 并返回解析后所对应的时间对象
 * @ param fmt
 * 时间格式
 * @ param s
 * 日期时间字符串
 * @ return 该时间字符串对应的时间对象 */
public static Date parse ( String fmt , String s ) throws ParseException { } }

implementation: return new SimpleDateFormat ( fmt ) . parse ( s ) ;


signature:
public class Times { /** * 方便的把时间换算成毫秒数
 * 支持几个单位 , s ( 秒 ) , m ( 分钟 ) , h ( 小时 ) , d ( 天 )
 * 比如 :
 * 100s - > 100000 < br >
 * 2m - > 120000 < br >
 * 3h - > 10800000 < br >
 * @ param tstr
 * 时间字符串
 * @ return 毫秒数 */
public static long toMillis ( String tstr ) { } }

implementation:
if ( Strings . isBlank ( tstr ) ) { return 0 ; } tstr = tstr . toLowerCase ( ) ; // FIXME 稍后改成正则判断
String tl = tstr . substring ( 0 , tstr . length ( ) - 1 ) ; String tu = tstr . substring ( tstr . length ( ) - 1 ) ; if ( TIME_S_EN . equals ( tu ) ) { return T_1S * Long . valueOf ( tl ) ; } if ( TIME_M_EN . equals ( tu ) ) { return T_1M * Long . valueOf ( tl ) ; } if ( TIME_H_EN . equals ( tu ) ) { return T_1H * Long . valueOf ( tl ) ; } if ( TIME_D_EN . equals ( tu ) ) { return T_1D * Long . valueOf ( tl ) ; } return Long . valueOf ( tstr ) ;


signature:
public class Times { /** * 比较2个字符串格式时间yyyy - MM - dd hh : mm : ss大小 2017-2-8 17:14:14
 * @ param t1
 * 第一个时间
 * @ param t2
 * 第二个时间
 * @ return true , 如果相等 */
public static boolean sDTcompare ( String t1 , String t2 ) { } }

implementation:
// 将字符串形式的时间转化为Date类型的时间
Date d1 = parseq ( DF_DATE_TIME , t1 ) ; Date d2 = parseq ( DF_DATE_TIME , t2 ) ; // Date类的一个方法 , 如果a早于b返回true , 否则返回false
if ( d1 . before ( d2 ) ) return true ; else return false ;


signature:
public class Times { /** * Unix时间戳转String日期
 * @ param timestamp
 * 时间戳
 * @ param sf
 * 日期格式
 * @ return 日期字符串 */
public static String ts2S ( long timestamp , String sf ) { } }

implementation: DateFormat format = new SimpleDateFormat ( sf ) ; return format . format ( new Date ( Long . parseLong ( timestamp * 1000 + "" ) ) ) ;


signature:
public class Times { /** * 字符串yyyy - MM - dd HH : mm : ss时间转化成Unix时间戳
 * @ param str
 * 日期 , 符合yyyy - MM - dd HH : mm : ss
 * @ return timestamp 时间戳字符串 */
public static String sDT2TS ( String str , DateFormat df ) { } }

implementation: try { return "" + ( df . parse ( str ) . getTime ( ) / 1000 ) ; } catch ( Exception e ) { e . printStackTrace ( ) ; } return "0" ;


signature:
public class Times { /** * 获得某月的天数
 * @ param year
 * @ param month
 * @ return int 指定年月的天数 */
public static int getDaysOfMonth ( String year , String month ) { } }

implementation: int days = 0 ; if ( month . equals ( "1" ) || month . equals ( "3" ) || month . equals ( "5" ) || month . equals ( "7" ) || month . equals ( "8" ) || month . equals ( "10" ) || month . equals ( "12" ) ) { days = 31 ; } else if ( month . equals ( "4" ) || month . equals ( "6" ) || month . equals ( "9" ) || month . equals ( "11" ) ) { days = 30 ; } else { if ( ( Integer . parseInt ( year ) % 4 == 0 && Integer . parseInt ( year ) % 100 != 0 ) || Integer . parseInt ( year ) % 400 == 0 ) { days = 29 ; } else { days = 28 ; } } return days ;


signature:
public class Times { /** * 获取某年某月的天数
 * @ param year
 * int 年
 * @ param month
 * int 月份 [ 1-12 ] 月
 * @ return int 指定年月的天数 */
public static int getDaysOfMonth ( int year , int month ) { } }

implementation: Calendar calendar = Calendar . getInstance ( ) ; calendar . set ( year , month - 1 , 1 ) ; return calendar . getActualMaximum ( Calendar . DAY_OF_MONTH ) ;


signature:
public class Times { /** * 返回日期的年
 * @ param date
 * 指定的Date
 * @ return 指定时间的年份 */
public static int getYear ( Date date ) { } }

implementation: Calendar calendar = Calendar . getInstance ( ) ; calendar . setTime ( date ) ; return calendar . get ( Calendar . YEAR ) ;


signature:
public class Times { /** * 比较两个日期的年差
 * @ param before
 * 前一个日期 , 格式yyyy - MM - dd
 * @ param after
 * 后一个日期 , 格式yyyy - MM - dd
 * @ return 年份差值 */
public static int yearDiff ( String before , String after ) { } }

implementation: Date beforeDay = parseq ( DF_DATE , before ) ; Date afterDay = parseq ( DF_DATE , after ) ; return getYear ( afterDay ) - getYear ( beforeDay ) ;


signature:
public class Times { /** * 比较指定日期与当前日期的年差
 * @ param after
 * 指定的后一个日期 , 格式yyyy - MM - dd
 * @ return 年份差值 */
public static int yearDiffCurr ( String after ) { } }

implementation: Date beforeDay = new Date ( ) ; Date afterDay = parseq ( DF_DATE , after ) ; return getYear ( beforeDay ) - getYear ( afterDay ) ;


signature:
public class Times { /** * 比较指定日期与当前日期的天差
 * @ param before
 * 指定的前应日期 , 格式yyyy - MM - dd
 * @ return 天差 */
public static long dayDiffCurr ( String before ) { } }

implementation: Date currDate = parseq ( DF_DATE , sD ( now ( ) ) ) ; Date beforeDate = parseq ( DF_DATE , before ) ; return ( currDate . getTime ( ) - beforeDate . getTime ( ) ) / 86400000 ;


signature:
public class Times { /** * 根据生日获取星座
 * @ param birth
 * 日期格式为YYYY - mm - dd
 * @ return 星座 , 单一字符 */
public static String getAstro ( String birth ) { } }

implementation: if ( ! isDate ( birth ) ) { birth = "2000" + birth ; } if ( ! isDate ( birth ) ) { return "" ; } int month = Integer . parseInt ( birth . substring ( birth . indexOf ( "-" ) + 1 , birth . lastIndexOf ( "-" ) ) ) ; int day = Integer . parseInt ( birth . substring ( birth . lastIndexOf ( "-" ) + 1 ) ) ; String s = "魔羯水瓶双鱼牡羊金牛双子巨蟹狮子处女天秤天蝎射手魔羯" ; int [ ] arr = { 20 , 19 , 21 , 21 , 21 , 22 , 23 , 23 , 23 , 23 , 22 , 22 } ; int start = month * 2 - ( day < arr [ month - 1 ] ? 2 : 0 ) ; return s . substring ( start , start + 2 ) + "座" ;


signature:
public class Times { /** * 判断日期是否有效 , 包括闰年的情况
 * @ param date
 * 日期格式YYYY - mm - dd
 * @ return true , 如果合法 */
public static boolean isDate ( String date ) { } }


signature:
public class Times { /** * 取得指定日期过 years 年后的日期 ( 当 years 为负数表示指定年之前 ) ;
 * @ param date
 * 日期 为null时表示当天
 * @ param years
 * 相加 ( 相减 ) 的年数 */
public static Date nextYear ( Date date , int years ) { } }

implementation: Calendar cal = Calendar . getInstance ( ) ; if ( date != null ) { cal . setTime ( date ) ; } cal . add ( Calendar . YEAR , years ) ; return cal . getTime ( ) ;


signature:
public class Times { /** * 取得指定日期过 months 月后的日期 ( 当 months 为负数表示指定月之前 ) ;
 * @ param date
 * 日期 为null时表示当天
 * @ param months
 * 相加 ( 相减 ) 的月数 */
public static Date nextMonth ( Date date , int months ) { } }

implementation: Calendar cal = Calendar . getInstance ( ) ; if ( date != null ) { cal . setTime ( date ) ; } cal . add ( Calendar . MONTH , months ) ; return cal . getTime ( ) ;


signature:
public class Times { /** * 取得指定日期过 day 周后的日期 ( 当 day 为负数表示指定月之前 )
 * @ param date
 * 日期 为null时表示当天 */
public static Date nextWeek ( Date date , int week ) { } }

implementation: Calendar cal = Calendar . getInstance ( ) ; if ( date != null ) { cal . setTime ( date ) ; } cal . add ( Calendar . WEEK_OF_MONTH , week ) ; return cal . getTime ( ) ;