'Language'에 해당되는 글 463건

  1. 2015.05.20 Pro*C 가이드/사이트
  2. 2015.01.09 PropertyEditorRegistrySupport.java : private void createDefaultEditors()
  3. 2014.12.12 구글맵(차트)
  4. 2014.12.10 jQuery Mask Plugin
  5. 2014.12.08 jQuery checkbox 컨트롤
  6. 2014.12.01 Java Reflection - Dynamic Class Loading and Reloading
  7. 2014.12.01 Java Reflection - Dynamic Proxies
  8. 2014.12.01 Java Reflection - Arrays
  9. 2014.12.01 Java Reflection - Generics
  10. 2014.12.01 Java Reflection - Annotations

Pro*C 가이드/사이트

Language/Pro*C 2015. 5. 20. 15:18

1. 번역 가이드 사이트

http://younbok.egloos.com/category/Oracle%20Warehouse


2, 오라클 가이드 사이트

http://docs.oracle.com/cd/B19306_01/appdev.102/b14407/toc.htm


3. 가이드 자료


ProC_Guide_Oracle.zip


ProC_Guide_Simple.pdf



:

PropertyEditorRegistrySupport.java : private void createDefaultEditors()

Language/JAVA 2015. 1. 9. 14:45

private void createDefaultEditors() { this.defaultEditors = new HashMap<Class<?>, PropertyEditor>(64); // Simple editors, without parameterization capabilities. // The JDK does not contain a default editor for any of these target types. this.defaultEditors.put(Charset.class, new CharsetEditor()); this.defaultEditors.put(Class.class, new ClassEditor()); this.defaultEditors.put(Class[].class, new ClassArrayEditor()); this.defaultEditors.put(Currency.class, new CurrencyEditor()); this.defaultEditors.put(File.class, new FileEditor()); this.defaultEditors.put(InputStream.class, new InputStreamEditor()); this.defaultEditors.put(InputSource.class, new InputSourceEditor()); this.defaultEditors.put(Locale.class, new LocaleEditor()); this.defaultEditors.put(Pattern.class, new PatternEditor()); this.defaultEditors.put(Properties.class, new PropertiesEditor()); this.defaultEditors.put(Resource[].class, new ResourceArrayPropertyEditor()); this.defaultEditors.put(TimeZone.class, new TimeZoneEditor()); this.defaultEditors.put(URI.class, new URIEditor()); this.defaultEditors.put(URL.class, new URLEditor()); this.defaultEditors.put(UUID.class, new UUIDEditor()); // Default instances of collection editors. // Can be overridden by registering custom instances of those as custom editors. this.defaultEditors.put(Collection.class, new CustomCollectionEditor(Collection.class)); this.defaultEditors.put(Set.class, new CustomCollectionEditor(Set.class)); this.defaultEditors.put(SortedSet.class, new CustomCollectionEditor(SortedSet.class)); this.defaultEditors.put(List.class, new CustomCollectionEditor(List.class)); this.defaultEditors.put(SortedMap.class, new CustomMapEditor(SortedMap.class)); // Default editors for primitive arrays. this.defaultEditors.put(byte[].class, new ByteArrayPropertyEditor()); this.defaultEditors.put(char[].class, new CharArrayPropertyEditor()); // The JDK does not contain a default editor for char! this.defaultEditors.put(char.class, new CharacterEditor(false)); this.defaultEditors.put(Character.class, new CharacterEditor(true)); // Spring's CustomBooleanEditor accepts more flag values than the JDK's default editor. this.defaultEditors.put(boolean.class, new CustomBooleanEditor(false)); this.defaultEditors.put(Boolean.class, new CustomBooleanEditor(true)); // The JDK does not contain default editors for number wrapper types! // Override JDK primitive number editors with our own CustomNumberEditor. this.defaultEditors.put(byte.class, new CustomNumberEditor(Byte.class, false)); this.defaultEditors.put(Byte.class, new CustomNumberEditor(Byte.class, true)); this.defaultEditors.put(short.class, new CustomNumberEditor(Short.class, false)); this.defaultEditors.put(Short.class, new CustomNumberEditor(Short.class, true)); this.defaultEditors.put(int.class, new CustomNumberEditor(Integer.class, false)); this.defaultEditors.put(Integer.class, new CustomNumberEditor(Integer.class, true)); this.defaultEditors.put(long.class, new CustomNumberEditor(Long.class, false)); this.defaultEditors.put(Long.class, new CustomNumberEditor(Long.class, true)); this.defaultEditors.put(float.class, new CustomNumberEditor(Float.class, false)); this.defaultEditors.put(Float.class, new CustomNumberEditor(Float.class, true)); this.defaultEditors.put(double.class, new CustomNumberEditor(Double.class, false)); this.defaultEditors.put(Double.class, new CustomNumberEditor(Double.class, true)); this.defaultEditors.put(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, true)); this.defaultEditors.put(BigInteger.class, new CustomNumberEditor(BigInteger.class, true)); // Only register config value editors if explicitly requested. if (this.configValueEditorsActive) { StringArrayPropertyEditor sae = new StringArrayPropertyEditor(); this.defaultEditors.put(String[].class, sae); this.defaultEditors.put(short[].class, sae); this.defaultEditors.put(int[].class, sae); this.defaultEditors.put(long[].class, sae); } }




응용 



package net.slipp.web; import java.beans.PropertyEditor; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.propertyeditors.CustomBooleanEditor; import org.springframework.beans.propertyeditors.CustomNumberEditor; import org.springframework.mock.web.MockHttpServletRequest; public class ReflectionTest { private static Logger log = LoggerFactory.getLogger(ReflectionTest.class); @SuppressWarnings("serial") private static Map<Class<?>, PropertyEditor> defaultEditors = new HashMap<Class<?>, PropertyEditor>() { { put(boolean.class, new CustomBooleanEditor(false)); put(Boolean.class, new CustomBooleanEditor(true)); put(byte.class, new CustomNumberEditor(Byte.class, false)); put(Byte.class, new CustomNumberEditor(Byte.class, true)); put(int.class, new CustomNumberEditor(Integer.class, false)); put(Integer.class, new CustomNumberEditor(Integer.class, true)); put(long.class, new CustomNumberEditor(Long.class, false)); put(Long.class, new CustomNumberEditor(Long.class, true)); } }; @Test public void populateFromRequestToUser() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("userId", "test"); request.addParameter("name", "슬립"); request.addParameter("userNo", "12356"); request.addParameter("age", "35"); MockUser user = new MockUser(); Field[] fields = MockUser.class.getDeclaredFields(); for (Field field : fields) { log.debug("field name : {}", field.getName()); field.setAccessible(true); String value = request.getParameter(field.getName()); if (field.getType() == String.class) { field.set(user, value); continue; } PropertyEditor propertyEditor = defaultEditors.get(field.getType()); if (propertyEditor != null) { propertyEditor.setAsText(value); field.set(user, propertyEditor.getValue()); } } log.debug("User : {}", user); } private class MockUser { private long userNo; private Integer age; private String userId; private String name; @Override public String toString() { return "MockUser [userNo=" + userNo + ", age=" + age + ", userId=" + userId + ", name=" + name + "]"; } } }



출처 http://slipp.net/questions/85


'Language > JAVA' 카테고리의 다른 글

java class loader #1  (1) 2016.08.04
[Java] ClassLoader API  (0) 2016.08.04
Java Reflection - Dynamic Class Loading and Reloading  (0) 2014.12.01
Java Reflection - Dynamic Proxies  (0) 2014.12.01
Java Reflection - Arrays  (0) 2014.12.01
:

구글맵(차트)

Language/JAVASCRIPT 2014. 12. 12. 16:43

https://developers.google.com/chart/

https://developers.google.com/chart/

https://developers.google.com/maps/documentation/javascript/examples/overlay-hideshow?hl=ko

http://using.tistory.com/82

http://roadmaps.kr/grboard/board.php?id=tips&articleNo=19

http://jsfiddle.net/msoliman85/XyFDM/ 


<!DOCTYPE html>
<html>
 
<head>
   
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
   
<meta charset="utf-8">
   
<title>Showing/Hiding overlays</title>
   
<style>
      html
, body, #map-canvas {
       
height: 100%;
       
margin: 0px;
       
padding: 0px
     
}
     
#panel {
       
position: absolute;
       
top: 5px;
       
left: 50%;
       
margin-left: -180px;
       
z-index: 5;
       
background-color: #fff;
       
padding: 5px;
       
border: 1px solid #999;
     
}
   
</style>
   
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
   
<script>
// This example adds hide() and show() methods to a custom overlay's prototype.
// These methods toggle the visibility of the container <div>.
// Additionally, we add a toggleDOM() method, which attaches or detaches the
// overlay to or from the map.

var overlay;

USGSOverlay.prototype = new google.maps.OverlayView();

function initialize() {
 
var myLatLng = new google.maps.LatLng(62.323907, -150.109291);
 
var mapOptions = {
    zoom
: 11,
    center
: myLatLng,
    mapTypeId
: google.maps.MapTypeId.SATELLITE
 
};

 
var map = new google.maps.Map(document.getElementById('map-canvas'),
      mapOptions
);

 
var swBound = new google.maps.LatLng(62.281819, -150.287132);
 
var neBound = new google.maps.LatLng(62.400471, -150.005608);
 
var bounds = new google.maps.LatLngBounds(swBound, neBound);

 
// The photograph is courtesy of the U.S. Geological Survey.
 
var srcImage = 'https://developers.google.com/maps/documentation/javascript/';
  srcImage
+= 'examples/full/images/talkeetna.png';

  overlay
= new USGSOverlay(bounds, srcImage, map);
}

/** @constructor */
function USGSOverlay(bounds, image, map) {

 
// Now initialize all properties.
 
this.bounds_ = bounds;
 
this.image_ = image;
 
this.map_ = map;

 
// Define a property to hold the image's div. We'll
 
// actually create this div upon receipt of the onAdd()
 
// method so we'll leave it null for now.
 
this.div_ = null;

 
// Explicitly call setMap on this overlay
 
this.setMap(map);
}

/**
 * onAdd is called when the map's panes are ready and the overlay has been
 * added to the map.
 */

USGSOverlay.prototype.onAdd = function() {

 
var div = document.createElement('div');
  div
.style.border = 'none';
  div
.style.borderWidth = '0px';
  div
.style.position = 'absolute';

 
// Create the img element and attach it to the div.
 
var img = document.createElement('img');
  img
.src = this.image_;
  img
.style.width = '100%';
  img
.style.height = '100%';
  div
.appendChild(img);

 
this.div_ = div;

 
// Add the element to the "overlayImage" pane.
 
var panes = this.getPanes();
  panes
.overlayImage.appendChild(this.div_);
};

USGSOverlay.prototype.draw = function() {

 
// We use the south-west and north-east
 
// coordinates of the overlay to peg it to the correct position and size.
 
// To do this, we need to retrieve the projection from the overlay.
 
var overlayProjection = this.getProjection();

 
// Retrieve the south-west and north-east coordinates of this overlay
 
// in LatLngs and convert them to pixel coordinates.
 
// We'll use these coordinates to resize the div.
 
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
 
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());

 
// Resize the image's div to fit the indicated dimensions.
 
var div = this.div_;
  div
.style.left = sw.x + 'px';
  div
.style.top = ne.y + 'px';
  div
.style.width = (ne.x - sw.x) + 'px';
  div
.style.height = (sw.y - ne.y) + 'px';
};

USGSOverlay.prototype.onRemove = function() {
 
this.div_.parentNode.removeChild(this.div_);
};

// [START region_hideshow]
// Set the visibility to 'hidden' or 'visible'.
USGSOverlay.prototype.hide = function() {
 
if (this.div_) {
   
// The visibility property must be a string enclosed in quotes.
   
this.div_.style.visibility = 'hidden';
 
}
};

USGSOverlay.prototype.show = function() {
 
if (this.div_) {
   
this.div_.style.visibility = 'visible';
 
}
};

USGSOverlay.prototype.toggle = function() {
 
if (this.div_) {
   
if (this.div_.style.visibility == 'hidden') {
     
this.show();
   
} else {
     
this.hide();
   
}
 
}
};

// Detach the map from the DOM via toggleDOM().
// Note that if we later reattach the map, it will be visible again,
// because the containing <div> is recreated in the overlay's onAdd() method.
USGSOverlay.prototype.toggleDOM = function() {
 
if (this.getMap()) {
   
// Note: setMap(null) calls OverlayView.onRemove()
   
this.setMap(null);
 
} else {
   
this.setMap(this.map_);
 
}
};
// [END region_hideshow]

google
.maps.event.addDomListener(window, 'load', initialize);

   
</script>
 
</head>
 
<body>

<!-- [START region_toolbar] -->
<!-- Add an input button to initiate the toggle method on the overlay. -->
   
<div id ="panel">
     
<input type="button" value="Toggle visibility" onclick="overlay.toggle();"></input>
     
<input type="button" value="Toggle DOM attachment" onclick="overlay.toggleDOM();"></input>
   
</div>
<!-- [END region_toolbar] -->
   
<div id="map-canvas"></div>
 
</body>
</html>

맞춤형 오버레이


Google 지도 API V3는 맞춤형 오버레이를 만들 수 있도록 OverlayView 클래스를 제공합니다. OverlayView는 오버레이를 만들 때 구현해야 할 여러 메소드를 제공하는 기본 클래스입니다. 클래스는 지도 상의 위치와 화면 좌표 간에 변환을 가능하게 하는 몇 개의 메소드도 제공합니다. 맞춤형 오버레이를 만들려면 다음과 같이 수행합니다.

  • 맞춤형 객체의 prototype을 google.maps.OverlayView()의 새 인스턴스로 설정합니다. 이렇게 하면 오버레이 클래스를 효과적으로 \'상속\'할 수 있습니다.
  • 맞춤형 오버레이의 생성자를 만들고 초기화 매개변수를 해당 생성자 내의 맞춤형 속성으로 설정합니다.
  • 프로토타입 내에서 onAdd() 메소드를 구현하고 지도에 오버레이를 연결합니다. OverlayView.onAdd()는 지도에 오버레이를 연결할 준비가 된 경우에 호출됩니다.
  • 프로토타입 내에서 draw() 메소드를 구현하고 객체의 시각적 표시를 처리합니다. 마찬가지로 OverlayView.draw()는 객체가 처음 표시되는 경우 호출됩니다.
  • 또한 onRemove() 메소드를 구현하여 오버레이 내에서 추가한 요소를 정리해야 합니다.

다음은 세부 단계에 대한 설명입니다.

오버레이 상속하기


OverlayView를 사용하여 간단한 이미지 오버레이를 만듭니다(V2 API 내의 GGroundOverlay와 유사). 이미지 경계 및 해당 지역의 USGS 이미지를 포함하는USGSOverlay 객체를 만듭니다. var overlay;

function initialize(){
  
var myLatLng =new google.maps.LatLng(62.323907,-150.109291);
  
var myOptions ={
    zoom
:11,
    center
: myLatLng,
    mapTypeId
: google.maps.MapTypeId.SATELLITE
  
};

  
var map =new google.maps.Map(document.getElementById(\"map_canvas\"), myOptions);

  
var swBound =new google.maps.LatLng(62.281819,-150.287132);
  
var neBound =new google.maps.LatLng(62.400471,-150.005608);
  
var bounds =new google.maps.LatLngBounds(swBound, neBound);

  
// Photograph courtesy of the U.S. Geological Survey
  
var srcImage =\'images/talkeetna.png\';
  overlay 
=newUSGSOverlay(bounds, srcImage, map);
} 다음으로 해당 클래스의 생성자를 만들고 전달된 매개변수를 새 객체의 속성으로 초기화합니다. OverlayView에서 USGSOverlay도 명시적으로 상속해야 합니다. 새 클래스의 prototype을 부모 클래스의 인스턴스로 설정하여 이 작업을 수행합니다. 여기서는 부모 클래스를 수정하려 하지 않으므로 부모 클래스 그 자체보다는 인스턴스로 프로토타입을 설정합니다.functionUSGSOverlay(bounds, image, map){

  
// Now initialize all properties.
  
this.bounds_ = bounds;
  
this.image_ = image;
  
this.map_ = map;

  
// We define a property to hold the image\'s
  
// div. We\'ll actually create this div
  
// upon receipt of the add() method so we\'ll
  
// leave it null for now.
  
this.div_ =null;

  
// Explicitly call setMap() on this overlay
  
this.setMap(map);
}

USGSOverlay.prototype =new google.maps.OverlayView();아직까지는 이 오버레이를 오버레이 생성자의 지도에 연결할 수 없습니다. 특히, 모든 지도 페인(객체가 지도에 표시되는 순서 지정)이 사용 가능한지 확인해야 합니다. 편리하게도, API는 이와 같은 경우가 발생했음을 알려주는 도우미 메소드를 제공합니다. 이 메소드는 다음 섹션에서 처리합니다.

오버레이 초기화하기


오버레이가 최초로 인스턴스화되어 표시할 준비가 완료되면 브라우저의 DOM을 사용하여 지도에 연결해야 합니다. API는 오버레이의 onAdd() 메소드를 호출하여 오버레이가 지도에 추가되었음을 표시합니다. 이미지를 포함할 를 만들어 이 메소드를 처리하고 \"\" 요소를 추가하고 이 요소를 에 연결한 다음, 마지막으로 지도의 페인(pane) 중 하나에 오버레이를 연결합니다. 페인(pane)은 DOM 트리에 있는 노드를 말합니다. MapPanes 유형의 페인(pane) 집합은 지도에 있는 여러 레이어의 스택 순서(stacking order)를 지정합니다. 다음과 같은 페인(pane)이 가능하며 아래쪽에서 위쪽으로 쌓여지는 순서로 열거됩니다.

  • MapPanes.mapPane
  • MapPanes.overlayLayer
  • MapPanes.overlayShadow
  • MapPanes.overlayImage
  • MapPanes.floatShadow
  • MapPanes.overlayMouseTarget
  • MapPanes.floatPane

Google은 \'지상 오버레이\' 이미지를 제공하므로 overlayLayer 지도 페인(pane)을 사용합니다. 지도 페인(pane)을 가지고 있으면 객체가 지도 페인에 자식으로 연결됩니다. USGSOverlay.prototype.onAdd =function(){

  
// Note: an overlay\'s receipt of onAdd() indicates that
  
// the map\'s panes are now available for attaching
  
// the overlay to the map via the DOM.

  
// Create the DIV and set some basic attributes.
  
var div = document.createElement(\'DIV\');
  div
.style.border =\"none\";
  div
.style.borderWidth =\"0px\";
  div
.style.position =\"absolute\";

  
// Create an IMG element and attach it to the DIV.
  
var img = document.createElement(\"img\");
  img
.src =this.image_;
  img
.style.width =\"100%\";
  img
.style.height =\"100%\";
  div
.appendChild(img);

  
// Set the overlay\'s div_ property to this DIV
  
this.div_ = div;

  
// We add an overlay to a map via one of the map\'s panes.
  
// We\'ll add this overlay to the overlayImage pane.
  
var panes =this.getPanes();
  panes
.overlayLayer.appendChild(div);
}

오버레이 그리기


위에서 특수한 시각적 표시를 실제로 호출한 것은 아닙니다. API는 지도에 오버레이를 그릴 때마다(처음 추가한 경우 포함) 오버레이에 별도의 draw() 메소드를 호출합니다. 따라서 이 draw() 메소드를 구현하고 getProjection()을 사용하여 오버레이의 MapCanvasProjection를 검색하고 객체의 오른쪽 상단과 왼쪽 하단 지점을 배치할 정확한 좌표를 계산합니다. 여기에서  크기가 조정됩니다. 이렇게 하면 오버레이 생성자에서 지정한 경계와 일치하도록 이미지 크기가 조정됩니다.USGSOverlay.prototype.draw =function(){

  
// Size and position the overlay. We use a southwest and northeast
  
// position of the overlay to peg it to the correct position and size.
  
// We need to retrieve the projection from this overlay to do this.
  
var overlayProjection =this.getProjection();

  
// Retrieve the southwest and northeast coordinates of this overlay
  
// in latlngs and convert them to pixels coordinates.
  
// We\'ll use these coordinates to resize the DIV.
  
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
  
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());

  
// Resize the image\'s DIV to fit the indicated dimensions.
  
var div =this.div_;
  div
.style.left = sw.x +\'px\';
  div
.style.top = ne.y +\'px\';
  div
.style.width =(ne.x - sw.x)+\'px\';
  div
.style.height =(sw.y - ne.y)+\'px\';
}

오버레이 삭제하기


onRemove() 메소드를 추가하여 지도에서 오버레이를 완전히 삭제할 수도 있습니다. 이 메소드는 오버레이의 map 속성을 null로 설정한 적이 있으면 API에서 자동으로 호출됩니다. USGSOverlay.prototype.onRemove =function(){
  
this.div_.parentNode.removeChild(this.div_);
  
this.div_ =null;
} 

예제 보기(overlay-simple.html) 

오버레이 숨기기 및 표시하기


오버레이를 단순히 만들거나 삭제하는 것이 아니라 숨기거나 표시하려면, 자신의 hide() 및 show() 메소드를 구현하여 오버레이의 가시성을 조정할 수 있습니다. 또는 지도의 DOM에서 오버레이를 분리할 수도 있습니다. 그러나 이 작업에는 비용이 약간 더 듭니다. 그리고 나서 오버레이를 지도의 DOM에 다시 연결하면 오버레이의 onAdd() 메소드가 다시 호출됩니다. 다음 예에서는 hide() 및 show() 메소드를 오버레이의 프로토타입에 추가합니다. 이 프로토타입은 컨테이너 의 가시성을 전환합니다. 또한 오버레이를 지도에 연결하거나 분리하는 toogleDOM() 메소드를 추가합니다. 가시성을 \"hidden\"으로 설정한 다음 toggleDOM()을 통해 DOM에서 지도를 분리할 경우, 지도를 나중에 다시 연결하면 지도는 포함하는 가 오버레이의 onAdd() 메소드에서 다시 만들어지기 때문에 다시 표시됩니다. // Note that the visibility property must be a string enclosed in quotes
USGSOverlay.prototype.hide =function(){
  
if(this.div_){
    
this.div_.style.visibility =\"hidden\";
  
}
}

USGSOverlay.prototype.show =function(){
  
if(this.div_){
    
this.div_.style.visibility =\"visible\";
  
}
}

USGSOverlay.prototype.toggle =function(){
  
if(this.div_){
    
if(this.div_.style.visibility ==\"hidden\"){
      
this.show();
    
}else{
      
this.hide();
    
}
  
}
}

USGSOverlay.prototype.toggleDOM =function(){
  
if(this.getMap()){
    
this.setMap(null);
  
}else{
    
this.setMap(this.map_);
  
}
}

// Now we add an input button to initiate the toggle method 
// on the specific overlay
<div id =\"toolbar\" width=\"100%; height:20px;\" style=\"text-align:center\">
  
<input type=\"button\" value=\"Toggle Visibility\" onclick=\"overlay.toggle();\">input>
  <input type=\"button\" value=\"Toggle DOM Attachment\" onclick=\"overlay.toggleDOM();\">input>
</div>




Google Maps + D3.js

d3.js 2014/02/11 11:08

Google Map위에 D3.js를 이용하여 마커 혹은 차트를 랜더링 하는 방법을 알아보자.


우선 Google Map 객체를 생성해보자.

Google Map 객체는 MapOption 줌레벨, 지도유형 등을 세팅 가능하다.

자세한 사항은 여기를 참고하기 바란다.

1
2
3
4
5
var map = new google.maps.Map(d3.select("#map").node(), {
    zoom: 12,
    center: new google.maps.LatLng(37.556059, 126.91009),
    mapTypeId: google.maps.MapTypeId.ROADMAP
});

여기서는 줌레벨과 초기 지도 센터 위도/경도 정보, 그리고 지도유형을 설정하였다.


이제 지도위에 마커정보(위도/경도)와 오버레이 객체를 생성한다.

지도위에 마커나 차트를 랜더링하기 위해서는 오버레이 객체를 생성해야 한다.

오버레이는 지도 상의 위도/경도 좌표에 연결된 객체를 말한다.

지도를 드래그하거나 확대/축소하면 연결된 오버레이도 함께 움직이며 지도에 '추가'하는 객체를 말한다.

1
2
var overlay = new google.maps.OverlayView();
var data = {"우리집":[126.8998768,37.4639925, 15,],"구로디지털단지역":[126.901472,37.48525, 15,2], /*생략*/};

data는 마커용 라벨정보와 위도/경도 정보 마커크기, 그리고 지하철 노선정보가 있다. 이 데이터를 이용하여 D3.js로 Circle를 랜더링할 수 있으며 이 글에서는 해당 정보에서 위도/경도만 사용하여 Pie Chart를 그려보고자 한다.

이제 오버레이에 Pie Chart를 랜더링 해보자.

1
2
3
4
5
overlay.onAdd = function() {
    var layer = d3.select(this.getPanes().overlayMouseTarget).append("div").attr("class", "stations");
         
    overlay.draw = function() {
        var projection = this.getProjection(), padding = 50;

여기까지 코드를 살펴보면 지도에 오버레이 랜더링할 준비가 되었을 경우(onAdd) stations div를 추가하고

오버레이에 초기 랜더링(draw)해준다. getProjection()은 Map상에 표시할 좌표를 계산하기 위한 메소드이다.

여기서 중요한건 overlayMouseTarget이다. 마커나 차트에 이벤트 바인딩을 하려면 해당 속성을 지정해줘야 한다.


이제 실제 마커할 D3.js소스를 추가해보자. 여기서 Pie Chart는 NVD3.js 라이브러리를 사용하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
        var marker = layer.selectAll("svg")
            .data(d3.entries(data))
            .each(transform)
            .enter().append("svg:svg")
            .each(transform)
            .attr("class", "marker");
 
        var pieData = [{"key": "One","value" : 29.765957771107} , {"key": "Two","value" : 10} ,{"key": "Three","value" : 32.807804682612} , {"key": "Four","value" : 196.45946739256}];
 
        nv.addGraph(function() {
            var chart = nv.models.pieChart()
                .x(function(d) { return d.key; })
                .y(function(d) { return d.value; })
                .margin({top: 0, right: 0, bottom: 0, left: 0})
                .showLabels(true)
                .labelThreshold(.05)
                .donut(true)
                .showLegend(false);
                           
            marker.datum(pieData).transition().duration(1200).call(chart);
 
            return chart;
        });
        function transform(d) {
            d = new google.maps.LatLng(d.value[1], d.value[0]);
            d = projection.fromLatLngToDivPixel(d);
            return d3.select(this)
                .style("left", (d.x-padding) + "px")
                .style("top", (d.y-padding) + "px");
        }
    }; //overlay.draw end
}; //overlay.onAdd end
overlay.setMap(map);

2번 라인 d3.entries(data)으로 data를 key, value로 변경해준다.

1
[{"key":"우리집","value":[126.8998768,37.4639925,15]},{"key":"구로디지털단지역","value":[126.901472,37.48525,15,2]}];

3번 라인에서 data 갯수만큼 each 메소드이용하여 24-30라인의 transform함수를 호출한다.

transform함수의 역활은 Map상에서 실제 마커될 Pie Chart의 픽셀 위치를 위도/경도를 이용하여 세팅해준다.

8번 라인은 Pie Chart의 Data이다. 10-23라인은 NVD3.js를 이용한 Pie Chart를 추가해준다.


Google Map은 zoom_changed, dragend와 같은 각종 이벤트를 제공한다.

해당 이벤트를 사용하는 방법도 간단하게 살펴보자.

1
2
3
4
5
6
7
8
9
google.maps.event.addListener(map, 'zoom_changed', function() {
    var zoomLevel = map.getZoom();
    var lat_south = map.getBounds().getSouthWest().lat();
    var lat_north = map.getBounds().getNorthEast().lat();
    var lng_west = map.getBounds().getSouthWest().lng();
    var lng_east = map.getBounds().getNorthEast().lng();
    var lat_center = map.getCenter().lat();
    var lng_center = map.getCenter().lng();
});

위 소스를 보면 Google Map에서 zoom_charged 이벤트가 발생할때 Map상에 줌레벨, 위도/경도 정보를 구할 수 있다.

해당 정보를 이용하여 현재 Map상에 표현할 마커나 차트정보를 서버 측에서 구해와 랜더링 할 수 있을 것이다.


참고자료








google.load( 'visualization', '1', { packages:['corechart'] });

function ChartMarker( options ) {
    this.setValues( options );
    
    this.$inner = $('<div>').css({
        position: 'relative',
        left: '-50%', top: '-50%',
        width: options.width,
        height: options.height,
        fontSize: '1px',
        lineHeight: '1px',
        backgroundColor: 'transparent',
        cursor: 'default'
    });

    this.$div = $('<div>')
        .append( this.$inner )
        .css({
            position: 'absolute',
            display: 'none'
        });
};

ChartMarker.prototype = new google.maps.OverlayView;

ChartMarker.prototype.onAdd = function() {
    $( this.getPanes().overlayMouseTarget ).append( this.$div );
};

ChartMarker.prototype.onRemove = function() {
    this.$div.remove();
};

ChartMarker.prototype.draw = function() {
    var marker = this;
    var projection = this.getProjection();
    var position = projection.fromLatLngToDivPixel( this.get('position') );

    this.$div.css({
        left: position.x,
        top: position.y,
        display: 'block'
    })

    this.$inner
        .html( '<img src="' + this.get('image') + '"/>' )
        .click( function( event ) {
            var events = marker.get('events');
            events && events.click( event );
        });
        
    this.chart = new google.visualization.PieChart( this.$inner[0] );
    this.chart.draw( this.get('chartData'), this.get('chartOptions') );
};

function initialize() {
    var latLng = new google.maps.LatLng( 40.708762, -74.006731 );

    var map = new google.maps.Map( $('#map_canvas')[0], {
        zoom: 15,
        center: latLng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    });
    
    var data = google.visualization.arrayToDataTable([
        [ 'Task', 'Hours per Day' ],
        [ 'Work', 1 ],
        [ 'Eat', 9 ]
    ]);
    var color = ['red','blue' ];
    
                 
    var rotation = [ 100, 140];
    for(i=0; i<2; i++){
                    
    var options = {
        fontSize: 8,
        backgroundColor: 'transparent',
        legend: 'none',
         pieStartAngle: rotation[i],
        pieSliceBorderColor: 'transparent',
       slices: {
            0: { color: color[i] },
            1: { color: 'transparent' }
          }        
    };
    var marker = new ChartMarker({
        map: map,
        position: latLng,
        width: '80px',
        height: '80px',
        chartData: data,
        chartOptions: options,
       
        events: {
            click: function( event ) {
                alert( 'Clicked marker' );
            }
        }
    });
}
};

$( initialize );



<script type="text/javascript" src="https://www.google.com/jsapi"></script><script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>


<div id="map_canvas" style="height: 400px; width: 400px"></div>


'Language > JAVASCRIPT' 카테고리의 다른 글

pply(), call() 메서드  (0) 2016.12.15
arguments 객체  (0) 2016.12.15
prototypejs  (0) 2013.11.13
마우스 커서 포지션 이동  (0) 2013.05.22
XMLHttpRequest 고급 기능  (1) 2013.04.29
:

jQuery Mask Plugin

Language/jQuery 2014. 12. 10. 10:22

http://plugins.jquery.com/mask/


Documentation

Basic Usage Examples

$(document).ready(function(){
  $('.date').mask('00/00/0000');
  $('.time').mask('00:00:00');
  $('.date_time').mask('00/00/0000 00:00:00');
  $('.cep').mask('00000-000');
  $('.phone').mask('0000-0000');
  $('.phone_with_ddd').mask('(00) 0000-0000');
  $('.phone_us').mask('(000) 000-0000');
  $('.mixed').mask('AAA 000-S0S');
  $('.cpf').mask('000.000.000-00', {reverse: true});
  $('.money').mask('000.000.000.000.000,00', {reverse: true});
  $('.money2').mask("#.##0,00", {reverse: true});
  $('.ip_address').mask('0ZZ.0ZZ.0ZZ.0ZZ', {
    translation: {
      'Z': {
        pattern: /[0-9]/, optional: true
      }
    }
  });
  $('.ip_address').mask('099.099.099.099');
  $('.percent').mask('##0,00%', {reverse: true});
  $('.clear-if-not-match').mask("00/00/0000", {clearIfNotMatch: true});
  $('.placeholder').mask("00/00/0000", {placeholder: "__/__/____"});
  $('.fallback').mask("00r00r0000", {
      translation: {
        'r': {
          pattern: /[\/]/, 
          fallback: '/'
        }, 
        placeholder: "__/__/____"
      }
    });
);

Callback Examples

var options =  { 
  onComplete: function(cep) {
    alert('CEP Completed!:' + cep);
  },
  onKeyPress: function(cep, event, currentField, options){
    console.log('An key was pressed!:', cep, ' event: ', event, 
                'currentField: ', currentField, ' options: ', options);
  },
  onChange: function(cep){
    console.log('cep changed! ', cep);
  },
  onInvalid: function(val, e, f, invalid, options){
    var error = invalid[0];
    console.log ("Digit: ", error.v, " is invalid for the position: ", error.p, ". We expect something like: ", error.e);
  }
};

$('.cep_with_callback').mask('00000-000', options);

On-the-fly mask change

var options =  {onKeyPress: function(cep, e, field, options){
  var masks = ['00000-000', '0-00-00-00'];
    mask = (cep.length>7) ? masks[1] : masks[0];
  $('.crazy_cep').mask(mask, options);
}};

$('.crazy_cep').mask('00000-000', options);

Mask as a function

var SPMaskBehavior = function (val) {
  return val.replace(/\D/g, '').length === 11 ? '(00) 00000-0000' : '(00) 0000-00009';
},
spOptions = {
  onKeyPress: function(val, e, field, options) {
      field.mask(SPMaskBehavior.apply({}, arguments), options);
    }
};

$('.sp_celphones').mask(SPMaskBehavior, spOptions);

Using HTML Notation Exemples

To get your mask applied with the data-mask attribute just use it as the same way you use with the $.mask function. 

<input type="text" name="field-name" data-mask="00/00/0000" />
Activating a reversible mask 

<input type="text" name="field-name" data-mask="00/00/0000" data-mask-reverse="true" />
Using clearIfNotMatch option 

<input type="text" name="field-name" data-mask="00/00/0000" data-mask-clearifnotmatch="true" />

Translation

Teach to jQuery Mask Plugin how to apply your mask: 

// now the digit 0 on your mask pattern will be interpreted 
// as valid characters like 0,1,2,3,4,5,6,7,8,9 and *
$('.your-field').mask('00/00/0000', {'translation': {0: {pattern: /[0-9*]/}}});
By default, jQuery Mask Plugin only reconizes the logical digit A (Numbers and Letters) and S (A-Za-z) but you can extend or modify this behaviour by telling to jQuery Mask Plugin how to interpret those logical digits. 

$('.your-field').mask('AA/SS/YYYY', {'translation': {
                                        A: {pattern: /[A-Za-z0-9]/}, 
                                        S: {pattern: /[A-Za-z]/},  
                                        Y: {pattern: /[0-9]/}
                                      }
                                });
Now jQuery Mask Plugin knows the logic digit Y and you can create your own pattern. 

Optional digits


You can also tell to jQuery Mask which digit is optional, to create a IP mask for example: 

// way 1
$('.ip_address').mask('099.099.099.099');
// way 2
$('.ip_address').mask('0ZZ.0ZZ.0ZZ.0ZZ', {translation:  {'Z': {pattern: /[0-9]/, optional: true}}});
Now, all Z digits in your masks is optional. 

Recursive digits


With jQuery Mask Plugin you can also define recursive patterns inside your mask: 

$('.money_example').mask('#.##0,00', {reverse: true});
With example above the mask will be placed from the right to the left (that's why reverse:true is defined). As soon as you start typing, a "0,00" will be applied followed by repeating recursively the following pattern "#.##". The result could be something like: 1.234.567,890. 

You can also use that kind of feature to define what kind of data could be typed inside of a field:
$('.example').mask('0#');
Now only numbers will be allowed inside your form field. 

Fallback digits

When a user types a invalid char for the current position the plugin will replace it by its fallback instead of erasing them.
$('.field_with_fallback').mask("00r00r0000", {
  translation: {
    'r': {
      pattern: /[\/]/, 
      fallback: '/'
    }, 
    placeholder: "__/__/____"
  }
});

Removing the mask

$('.date').unmask();

Getting the unmasked typed value

$('.date').cleanVal();

Customization

jQuery Mask Plugin has a few default options that you can overwrite as you like:

Field Options

var custom_options = {
  byPassKeys: [8, 9, 37, 38, 39, 40],
  translation: {
                '0': {pattern: /\d/}, 
                '9': {pattern: /\d/, optional: true}, 
                '#': {pattern: /\d/, recursive: true}, 
                'A': {pattern: /[a-zA-Z0-9]/}, 
                'S': {pattern: /[a-zA-Z]/}
            };
};
byPassKeys list of keyboard's keyCode that you want to be ignored when it was pressed. 
translation object with all digits that should be interpreted as a special chars and its regex representation. 

Global Options

// nonInput: elements we consider nonInput
// dataMask: we mask data-mask elements by default
// watchInputs: watch for dynamically added inputs by default
// watchDataMask: by default we disabled the watcher for dynamically added data-mask elements by default (performance reasons)
 $.jMaskGlobals = {
    nonInput: 'td,span,div', 
    dataMask: true, 
    watchInterval: 300,
    watchInputs: true, 
    watchDataMask: false,
    byPassKeys: [9, 16, 17, 18, 36, 37, 38, 39, 40, 91],
    translation: {
      '0': {pattern: /\d/},
      '9': {pattern: /\d/, optional: true},
      '#': {pattern: /\d/, recursive: true},
      'A': {pattern: /[a-zA-Z0-9]/},
      'S': {pattern: /[a-zA-Z]/}
    }
  };


'Language > jQuery' 카테고리의 다른 글

jQuery Plugin - Plugin 작성 가이드  (0) 2016.12.15
jQuery:$.extend() 와 $.fn.extend()  (0) 2016.12.15
jQuery checkbox 컨트롤  (0) 2014.12.08
jQuery grid - jqGrid  (0) 2014.11.20
jQuery BlockUI Plugin  (0) 2014.11.20
:

jQuery checkbox 컨트롤

Language/jQuery 2014. 12. 8. 12:37

checkbox checked 여부 : 

- id로 체크하는 경우

$('input:checkbox[id="checkbox_id"]').is(":checked") == true


- name으로 체크하는 경우

$('input:checkbox[name="checkbox_name"]').is(":checked") == true


- $('input[id="checkbox_id"]') + 옵션 형태로 작성 가능

 $('input[name="checkbox_name"]').is(":checked") 



checkbox 갯수 확인 : 

- 전체 갯수 

$('input:checkbox[id="checkbox_name"]').length 


- 선택된 갯수

$('input:checkbox[id="checkbox_name"]:checked').length 


- 배열을 사용할 경우

$('input:checkbox[id ='checkbox_name[]"]:checked').length

$("input[id ='checkbox_name[]']:checked").length



checkbox checked 처리 :

- 개별

$('input:checkbox[id="checkbox_id"]').attr("checked", true);


- 전체(동일한 id나 name으로 여래개인 경우 전체를 컨트롤 가능)

$('input:checkbox[name="checkbox_name"]').each(function() {

this.checked = true;

});



checkbox value 값 가져오기 :

$('input:checkbox[id="checkbox_id"]').val();

 

 출처 - http://isstory83.tistory.com/112

'Language > jQuery' 카테고리의 다른 글

jQuery:$.extend() 와 $.fn.extend()  (0) 2016.12.15
jQuery Mask Plugin  (0) 2014.12.10
jQuery grid - jqGrid  (0) 2014.11.20
jQuery BlockUI Plugin  (0) 2014.11.20
jquery ui plug-in  (0) 2014.11.18
:

Java Reflection - Dynamic Class Loading and Reloading

Language/JAVA 2014. 12. 1. 11:43

It is possible to load and reload classes at runtime in Java, though it is not as straightforward as one might have hoped. This text will explain when and how you can load and reload classes in Java.

You can argue whether Java's dynamic class loading features are really part of Java Reflection, or a part of the core Java platform. Anyways, the article has been put in the Java Reflection trail in lack of a better place to put it.

The ClassLoader

All classes in a Java application are loaded using some subclass of java.lang.ClassLoader. Loading classes dynamically must therefore also be done using a java.lang.ClassLoader subclass.

When a class is loaded, all classes it references are loaded too. This class loading pattern happens recursively, until all classes needed are loaded. This may not be all classes in the application. Unreferenced classes are not loaded until the time they are referenced.

The ClassLoader Hierarchy

Class loaders in Java are organized into a hierarchy. When you create a new standard Java ClassLoader you must provide it with a parent ClassLoader. If a ClassLoader is asked to load a class, it will ask its parent class loader to load it. If the parent class loader can't find the class, the child class loader then tries to load it itself.

Class Loading

The steps a given class loader uses when loading classes are:

  1. Check if the class was already loaded.
  2. If not loaded, ask parent class loader to load the class.
  3. If parent class loader cannot load class, attempt to load it in this class loader.

When you implement a class loader that is capable of reloading classes you will need to deviate a bit from this sequence. The classes to reload should not be requested loaded by the parent class loader. More on that later.

Dynamic Class Loading

Loading a class dynamically is easy. All you need to do is to obtain a ClassLoader and call its loadClass()method. Here is an example:

public class MainClass {

  public static void main(String[] args){

    ClassLoader classLoader = MainClass.class.getClassLoader();

    try {
        Class aClass = classLoader.loadClass("com.jenkov.MyClass");
        System.out.println("aClass.getName() = " + aClass.getName());
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

}

Dynamic Class Reloading

Dynamic class reloading is a bit more challenging. Java's builtin Class loaders always checks if a class is already loaded before loading it. Reloading the class is therefore not possible using Java's builtin class loaders. To reload a class you will have to implement your own ClassLoader subclass.

Even with a custom subclass of ClassLoader you have a challenge. Every loaded class needs to be linked. This is done using the ClassLoader.resolve() method. This method is final, and thus cannot be overridden in yourClassLoader subclass. The resolve() method will not allow any given ClassLoader instance to link the same class twice. Therefore, everytime you want to reload a class you must use a new instance of your ClassLoadersubclass. This is not impossible, but necessary to know when designing for class reloading.

Designing your Code for Class Reloading

As stated earlier you cannot reload a class using a ClassLoader that has already loaded that class once. Therefore you will have to reload the class using a different ClassLoader instance. But this poses som new challenges.

Every class loaded in a Java application is identified by its fully qualified name (package name + class name), and theClassLoader instance that loaded it. That means, that a class MyObject loaded by class loader A, is not the same class as the MyObject class loaded with class loader B. Look at this code:

MyObject object = (MyObject)
    myClassReloadingFactory.newInstance("com.jenkov.MyObject");

Notice how the MyObject class is referenced in the code, as the type of the object variable. This causes theMyObject class to be loaded by the same class loader that loaded the class this code is residing in.

If the myClassReloadingFactory object factory reloads the MyObject class using a different class loader than the class the above code resides in, you cannot cast the instance of the reloaded MyObject class to the MyObject type of the object variable. Since the two MyObject classes were loaded with different class loaders, the are regarded as different classes, even if they have the same fully qualified class name. Trying to cast an object of the one class to a reference of the other will result in a ClassCastException.

It is possible to work around this limitation but you will have to change your code in either of two ways:

  1. Use an interface as the variable type, and just reload the implementing class.
  2. Use a superclass as the variable type, and just reload a subclass.

Here are two coresponding code examples:

MyObjectInterface object = (MyObjectInterface)
    myClassReloadingFactory.newInstance("com.jenkov.MyObject");
MyObjectSuperclass object = (MyObjectSuperclass)
    myClassReloadingFactory.newInstance("com.jenkov.MyObject");

Either of these two methods will work if the type of the variable, the interface or superclass, is not reloaded when the implementing class or subclass is reloaded.

To make this work you will of course need to implement your class loader to let the interface or superclass be loaded by its parent. When your class loader is asked to load the MyObject class, it will also be asked to load theMyObjectInterface class, or the MyObjectSuperclass class, since these are referenced from within theMyObject class. Your class loader must delegate the loading of those classes to the same class loader that loaded the class containing the interface or superclass typed variables.

ClassLoader Load / Reload Example

The text above has contained a lot of talk. Let's look at a simple example. Below is an example of a simpleClassLoader subclass. Notice how it delegates class loading to its parent except for the one class it is intended to be able to reload. If the loading of this class is delegated to the parent class loader, it cannot be reloaded later. Remember, a class can only be loaded once by the same ClassLoader instance.

As said earlier, this is just an example that serves to show you the basics of a ClassLoader's behaviour. It is not a production ready template for your own class loaders. Your own class loaders should probably not be limited to a single class, but a collection of classes that you know you will need to reload. In addition, you should probably not hardcode the class paths either.

public class MyClassLoader extends ClassLoader{

    public MyClassLoader(ClassLoader parent) {
        super(parent);
    }

    public Class loadClass(String name) throws ClassNotFoundException {
        if(!"reflection.MyObject".equals(name))
                return super.loadClass(name);

        try {
            String url = "file:C:/data/projects/tutorials/web/WEB-INF/" +
                            "classes/reflection/MyObject.class";
            URL myUrl = new URL(url);
            URLConnection connection = myUrl.openConnection();
            InputStream input = connection.getInputStream();
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            int data = input.read();

            while(data != -1){
                buffer.write(data);
                data = input.read();
            }

            input.close();

            byte[] classData = buffer.toByteArray();

            return defineClass("reflection.MyObject",
                    classData, 0, classData.length);

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

}


Below is an example use of the MyClassLoader.

public static void main(String[] args) throws
    ClassNotFoundException,
    IllegalAccessException,
    InstantiationException {

    ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader();
    MyClassLoader classLoader = new MyClassLoader(parentClassLoader);
    Class myObjectClass = classLoader.loadClass("reflection.MyObject");

    AnInterface2       object1 =
            (AnInterface2) myObjectClass.newInstance();

    MyObjectSuperClass object2 =
            (MyObjectSuperClass) myObjectClass.newInstance();

    //create new class loader so classes can be reloaded.
    classLoader = new MyClassLoader(parentClassLoader);
    myObjectClass = classLoader.loadClass("reflection.MyObject");

    object1 = (AnInterface2)       myObjectClass.newInstance();
    object2 = (MyObjectSuperClass) myObjectClass.newInstance();

}


Here is the reflection.MyObject class that is loaded using the class loader. Notice how it both extends a superclass and implements an interface. This is just for the sake of the example. In your own code you would only have to one of the two - extend or implement.

public class MyObject extends MyObjectSuperClass implements AnInterface2{
    //... body of class ... override superclass methods
    //    or implement interface methods
}

출처 - http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html


'Language > JAVA' 카테고리의 다른 글

[Java] ClassLoader API  (0) 2016.08.04
PropertyEditorRegistrySupport.java : private void createDefaultEditors()  (0) 2015.01.09
Java Reflection - Dynamic Proxies  (0) 2014.12.01
Java Reflection - Arrays  (0) 2014.12.01
Java Reflection - Generics  (0) 2014.12.01
:

Java Reflection - Dynamic Proxies

Language/JAVA 2014. 12. 1. 11:43

Using Java Reflection you create dynamic implementations of interfaces at runtime. You do so using the classjava.lang.reflect.Proxy. The name of this class is why I refer to these dynamic interface implementations as dynamic proxies. Dynamic proxies can be used for many different purposes, e.g. database connection and transaction management, dynamic mock objects for unit testing, and other AOP-like method intercepting purposes.

Creating Proxies

You create dynamic proxies using the Proxy.newProxyInstance() method. The newProxyInstance() methods takes 3 parameters:

  1. The ClassLoader that is to "load" the dynamic proxy class.
  2. An array of interfaces to implement.
  3. An InvocationHandler to forward all methods calls on the proxy to.

Here is an example:

InvocationHandler handler = new MyInvocationHandler();
MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
                            MyInterface.class.getClassLoader(),
                            new Class[] { MyInterface.class },
                            handler);

After running this code the proxy variable contains a dynamic implementation of the MyInterface interface. All calls to the proxy will be forwarded to the handler implementation of the general InvocationHandler interface. InvocationHandler's are covered i the next section.

InvocationHandler's

As mentioned earlier you must pass an InvocationHandler implementation to the Proxy.newProxyInstance()method. All method calls to the dynamic proxy are forwarded to this InvocationHandler implementation. Here is how the InvocationHandler interface looks:

public interface InvocationHandler{
  Object invoke(Object proxy, Method method, Object[] args)
         throws Throwable;
}

Here is an example implementation:

public class MyInvocationHandler implements InvocationHandler{

  public Object invoke(Object proxy, Method method, Object[] args)
  throws Throwable {
    //do something "dynamic"
  }
}

The proxy parameter passed to the invoke() method is the dynamic proxy object implementing the interface. Most often you don't need this object.

The Method object passed into the invoke() method represents the method called on the interface the dynamic proxy implements. From the Method object you can obtain the method name, parameter types, return type, etc. See the text on Methods for more information.

The Object[] args array contains the parameter values passed to the proxy when the method in the interface implemented was called. Note: Primitives (int, long etc) in the implemented interface are wrapped in their object counterparts (Integer, Long etc.).

Known Use Cases

Dynamic proxies are known to be used for at least the following purposes:

  • Database Connection and Transaction Management
  • Dynamic Mock Objects for Unit Testing
  • Adaptation of DI Container to Custom Factory Interfaces
  • AOP-like Method Interception

Database Connection and Transaction Management

The Spring framework has a transaction proxy that can start and commit / rollback a transaction for you. How this works is described in more detail in the text Advanced Connection and Transaction Demarcation and Propagation , so I'll only describe it briefly. The call sequence becomes something along this:

web controller --> proxy.execute(...);
  proxy --> connection.setAutoCommit(false);
  proxy --> realAction.execute();
    realAction does database work
  proxy --> connection.commit();

Dynamic Mock Objects for Unit Testing

The Butterfly Testing Tools makes use of dynamic proxies to implement dynamic stubs, mocks and proxies for unit testing. When testing a class A that uses another class B (interface really), you can pass a mock implementation of B into A instead of a real B. All method calls on B are now recorded, and you can set what return values the mock B is to return.

Furthermore Butterfly Testing Tools allow you to wrap a real B in a mock B, so that all method calls on the mock are recorded, and then forwarded to the real B. This makes it possible to check what methods were called on a real functioning B. For instance, if testing a DAO you can wrap the database connection in a mock. The DAO will not see the difference, and the DAO can read/write data to the database as usual since the mock forwards all calls to the database. But now you can check via the mock if the DAO uses the connection properly, for instance if theconnection.close() is called (or NOT called), if you expected that. This is normally not possible to determine from the return value of a DAO.

Adaptation of DI Container to Custom Factory Interfaces

The dependency injection container Butterfly Container has a powerful feature that allows you to inject the whole container into beans produced by it. But, since you don't want a dependency on the container interface, the container is capable of adapting itself to a custom factory interface of your design. You only need the interface. No implementation. Thus the factory interface and your class could look something like this:

public interface IMyFactory {
  Bean   bean1();
  Person person();
  ...
}
public class MyAction{

  protected IMyFactory myFactory= null;

  public MyAction(IMyFactory factory){
    this.myFactory = factory;
  }

  public void execute(){
    Bean bean = this.myFactory.bean();
    Person person = this.myFactory.person();
  }

}

When the MyAction class calls methods on the IMyFactory instance injected into its constructor by the container, the method calls are translated into calls to the IContainer.instance() method, which is the method you use to obtain instances from the container. That way an object can use Butterfly Container as a factory at runtime, rather than only to have dependencies injected into itself at creation time. And this without having any dependencies on any Butterfly Container specific interfaces.

AOP-like Method Interception

The Spring framework makes it possible to intercept method calls to a given bean, provided that bean implements some interface. The Spring framework wraps the bean in a dynamic proxy. All calls to the bean are then intercepted by the proxy. The proxy can decide to call other methods on other objects either before, instead of, or after delegating the method call to the bean wrapped.


출처 - http://tutorials.jenkov.com/java-reflection/dynamic-proxies.html


:

Java Reflection - Arrays

Language/JAVA 2014. 12. 1. 11:42

Working with arrays in Java Reflection can be a bit tricky at times. Especially if you need to obtain the Class object for a certain type of array, like int[] etc. This text will discuss how to both create arrays and get their class objects via Java Reflection.

Note: This text has been updated after reading Eyal Lupu's blog post 
"Two Side Notes About Arrays and Reflection" which commented on the first edition of this text. The current edition takes his comments into consideration.

java.lang.reflect.Array

Working with arrays via Java Reflection is done using the java.lang.reflect.Array class. Do not confuse this class with the java.util.Arrays class in the Java Collections suite, which contains utility methods for sorting arrays, converting them to collections etc.

Creating Arrays

Creating arrays via Java Reflection is done using the java.lang.reflect.Array class. Here is an example showing how to create an array:

int[] intArray = (int[]) Array.newInstance(int.class, 3);

This code sample creates an array of int. The first parameter int.class given to the Array.newInstance()method tells what type each element in the array should be of. The second parameter states how many elements the array should have space for.

Accessing Arrays

It is also possible to access the elements of an array using Java Reflection. This is done via the Array.get(...)and Array.set(...) methods. Here is an example:

int[] intArray = (int[]) Array.newInstance(int.class, 3);

Array.set(intArray, 0, 123);
Array.set(intArray, 1, 456);
Array.set(intArray, 2, 789);

System.out.println("intArray[0] = " + Array.get(intArray, 0));
System.out.println("intArray[1] = " + Array.get(intArray, 1));
System.out.println("intArray[2] = " + Array.get(intArray, 2));

This code sample will print out this:

intArray[0] = 123
intArray[1] = 456
intArray[2] = 789

Obtaining the Class Object of an Array

One of the problems I ran into when implementing the script language in Butterfly DI Container was how to obtain theClass object for arrays via Java Reflection. Using non-reflection code you can do like this:

Class stringArrayClass = String[].class;

Doing this using Class.forName() is not quite straightforward. For instance, you can access the primitive int array class object like this:

Class intArray = Class.forName("[I");

The JVM represents an int via the letter I. The [ on the left means it is the class of an int array I am interested in. This works for all other primitives too.

For objects you need to use a slightly different notation:

Class stringArrayClass = Class.forName("[Ljava.lang.String;");

Notice the [L to the left of the class name, and the ; to the right. This means an array of objects with the given type.

As a side note, you cannot obtain the class object of primitives using Class.forName(). Both of the examples below result in a ClassNotFoundException:

Class intClass1 = Class.forName("I");
Class intClass2 = Class.forName("int");

I usually do something like this to obtain the class name for primitives as well as objects:

public Class getClass(String className){
  if("int" .equals(className)) return int .class;
  if("long".equals(className)) return long.class;
  ...
  return Class.forName(className);
}

Once you have obtained the Class object of a type there is a simple way to obtain the Class of an array of that type. The solution, or workaround as you might call it, is to create an empty array of the desired type and obtain the class object from that empty array. It's a bit of a cheat, but it works. Here is how that looks:

Class theClass = getClass(theClassName);
Class stringArrayClass = Array.newInstance(theClass, 0).getClass();

This presents a single, uniform method to access the array class of arrays of any type. No fiddling with class names etc.

To make sure that the Class object really is an array, you can call the Class.isArray() method to check:

Class stringArrayClass = Array.newInstance(String.class, 0).getClass();
System.out.println("is array: " + stringArrayClass.isArray());

Obtaining the Component Type of an Array

Once you have obtained the Class object for an array you can access its component type via theClass.getComponentType() method. The component type is the type of the items in the array. For instance, the component type of an int[] array is the int.class Class object. The component type of a String[] array is thejava.lang.String Class object.

Here is an example of accessing the component type array:

String[] strings = new String[3];
Class stringArrayClass = strings.getClass();
Class stringArrayComponentType = stringArrayClass.getComponentType();
System.out.println(stringArrayComponentType);

This example will print out the text "java.lang.String" which is the component type of the String array.


출처 - http://tutorials.jenkov.com/java-reflection/arrays.html


:

Java Reflection - Generics

Language/JAVA 2014. 12. 1. 11:42

I have often read in articles and forums that all Java Generics information is erased at compile time so that you cannot access any of that information at runtime. This is not entirely true though. It is possible to access generics information at runtime in a handful of cases. These cases actually cover several of our needs for Java Generics information. This text explains these cases.

The Generics Reflection Rule of Thumb

Using Java Generics typically falls into one of two different situations:

  1. Declaring a class/interface as being parameterizable.
  2. Using a parameterizable class.

When you write a class or interface you can specify that it should be paramerizable. This is the case with thejava.util.List interface. Rather than create a list of Object you can parameterize java.util.List to create a list of say String.

When runtime inspecting a parameterizable type itself, like java.util.List, there is no way of knowing what type is has been parameterized to. This makes sense since the type can be parameterized to all kinds of types in the same application. But, when you inspect the method or field that declares the use of a parameterized type, you can see at runtime what type the paramerizable type was parameterized to. In short:

You cannot see on a type itself what type it is parameterized to a runtime, but you can see it in fields and methods where it is used and parameterized. Its concrete parameterizations in other words.

The following sections take a closer look at these situations.

Generic Method Return Types

If you have obtained a java.lang.reflect.Method object it is possible to obtain information about its generic return type. This cannot be any of the Method objects in the parameterized type, but in the class that uses the parameterized type. You can read how to obtain Method objects in the text "Java Generics: Methods". Here is an example class with a method having a parameterized return type:

public class MyClass {

  protected List<String> stringList = ...;

  public List<String> getStringList(){
    return this.stringList;
  }
}

In this class it is possible to obtain the generic return type of the getStringList() method. In other words, it is possible to detect that getStringList() returns a List<String> and not just a List. Here is how:

Method method = MyClass.class.getMethod("getStringList", null);

Type returnType = method.getGenericReturnType();

if(returnType instanceof ParameterizedType){
    ParameterizedType type = (ParameterizedType) returnType;
    Type[] typeArguments = type.getActualTypeArguments();
    for(Type typeArgument : typeArguments){
        Class typeArgClass = (Class) typeArgument;
        System.out.println("typeArgClass = " + typeArgClass);
    }
}

This piece of code will print out the text "typeArgClass = java.lang.String". The Type[] array typeArguments array will contain one item - a Class instance representing the class java.lang.StringClass implements the Typeinterface.

Generic Method Parameter Types

You can also access the generic types of parameter types at runtime via Java Reflection. Here is an example class with a method taking a parameterized List as parameter:

public class MyClass {
  protected List<String> stringList = ...;

  public void setStringList(List<String> list){
    this.stringList = list;
  }
}

You can access the generic parameter types of the method parameters like this:

method = Myclass.class.getMethod("setStringList", List.class);

Type[] genericParameterTypes = method.getGenericParameterTypes();

for(Type genericParameterType : genericParameterTypes){
    if(genericParameterType instanceof ParameterizedType){
        ParameterizedType aType = (ParameterizedType) genericParameterType;
        Type[] parameterArgTypes = aType.getActualTypeArguments();
        for(Type parameterArgType : parameterArgTypes){
            Class parameterArgClass = (Class) parameterArgType;
            System.out.println("parameterArgClass = " + parameterArgClass);
        }
    }
}

This code will print out the text "parameterArgType = java.lang.String". The Type[] array parameterArgTypes array will contain one item - a Class instance representing the class java.lang.StringClass implements the Typeinterface.

Generic Field Types

It is also possible to access the generic types of public fields. Fields are class member variables - either static or instance variables. You can read about obtaining Field objects in the text "Java Generics: Fields". Here is the example from earlier, with an instance field called stringList.

public class MyClass {
  public List<String> stringList = ...;
}
Field field = MyClass.class.getField("stringList");

Type genericFieldType = field.getGenericType();

if(genericFieldType instanceof ParameterizedType){
    ParameterizedType aType = (ParameterizedType) genericFieldType;
    Type[] fieldArgTypes = aType.getActualTypeArguments();
    for(Type fieldArgType : fieldArgTypes){
        Class fieldArgClass = (Class) fieldArgType;
        System.out.println("fieldArgClass = " + fieldArgClass);
    }
}

This code will print out the text "fieldArgClass = java.lang.String". The Type[] array fieldArgTypes array will contain one item - a Class instance representing the class java.lang.StringClass implements the Typeinterface.


출처 - http://tutorials.jenkov.com/java-reflection/generics.html

'Language > JAVA' 카테고리의 다른 글

Java Reflection - Dynamic Proxies  (0) 2014.12.01
Java Reflection - Arrays  (0) 2014.12.01
Java Reflection - Annotations  (0) 2014.12.01
Java Reflection - Private Fields and Methods  (0) 2014.12.01
Java Reflection - Getters and Setters  (0) 2014.12.01
:

Java Reflection - Annotations

Language/JAVA 2014. 12. 1. 11:41

Using Java Reflection you can access the annotations attached to Java classes at runtime.

What are Java Annotations?

Annotations is a new feature from Java 5. Annotations are a kind of comment or meta data you can insert in your Java code. These annotations can then be processed at compile time by pre-compiler tools, or at runtime via Java Reflection. Here is an example of class annotation:

@MyAnnotation(name="someName",  value = "Hello World")
public class TheClass {
}

The class TheClass has the annotation @MyAnnotation written ontop. Annotations are defined like interfaces. Here is the MyAnnotation definition:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)

public @interface MyAnnotation {
    public String name();
    public String value();
}

The @ in front of the interface marks it as an annotation. Once you have defined the annotation you can use it in your code, as shown in the earlier examples.

The two directives in the annotation definition, @Retention(RetentionPolicy.RUNTIME) and@Target(ElementType.TYPE), specifies how the annotation is to be used.

@Retention(RetentionPolicy.RUNTIME) means that the annotation can be accessed via reflection at runtime. If you do not set this directive, the annotation will not be preserved at runtime, and thus not available via reflection.

@Target(ElementType.TYPE) means that the annotation can only be used ontop of types (classes and interfaces typically). You can also specify METHOD or FIELD, or you can leave the target out alltogether so the annotation can be used for both classes, methods and fields.

Java annotations are explained in more detail in my Java Annotations tutorial.

Class Annotations

You can access the annotations of a class, method or field at runtime. Here is an example that accesses the class annotations:

Class aClass = TheClass.class;
Annotation[] annotations = aClass.getAnnotations();

for(Annotation annotation : annotations){
    if(annotation instanceof MyAnnotation){
        MyAnnotation myAnnotation = (MyAnnotation) annotation;
        System.out.println("name: " + myAnnotation.name());
        System.out.println("value: " + myAnnotation.value());
    }
}

You can also access a specific class annotation like this:

Class aClass = TheClass.class;
Annotation annotation = aClass.getAnnotation(MyAnnotation.class);

if(annotation instanceof MyAnnotation){
    MyAnnotation myAnnotation = (MyAnnotation) annotation;
    System.out.println("name: " + myAnnotation.name());
    System.out.println("value: " + myAnnotation.value());
}

Method Annotations

Here is an example of a method with annotations:

public class TheClass {
  @MyAnnotation(name="someName",  value = "Hello World")
  public void doSomething(){}
}

You can access method annotations like this:

Method method = ... //obtain method object
Annotation[] annotations = method.getDeclaredAnnotations();

for(Annotation annotation : annotations){
    if(annotation instanceof MyAnnotation){
        MyAnnotation myAnnotation = (MyAnnotation) annotation;
        System.out.println("name: " + myAnnotation.name());
        System.out.println("value: " + myAnnotation.value());
    }
}

You can also access a specific method annotation like this:

Method method = ... // obtain method object
Annotation annotation = method.getAnnotation(MyAnnotation.class);

if(annotation instanceof MyAnnotation){
    MyAnnotation myAnnotation = (MyAnnotation) annotation;
    System.out.println("name: " + myAnnotation.name());
    System.out.println("value: " + myAnnotation.value());
}

Parameter Annotations

It is possible to add annotations to method parameter declarations too. Here is how that looks:

public class TheClass {
  public static void doSomethingElse(
        @MyAnnotation(name="aName", value="aValue") String parameter){
  }
}

You can access parameter annotations from the Method object like this:

Method method = ... //obtain method object
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
Class[] parameterTypes = method.getParameterTypes();

int i=0;
for(Annotation[] annotations : parameterAnnotations){
  Class parameterType = parameterTypes[i++];

  for(Annotation annotation : annotations){
    if(annotation instanceof MyAnnotation){
        MyAnnotation myAnnotation = (MyAnnotation) annotation;
        System.out.println("param: " + parameterType.getName());
        System.out.println("name : " + myAnnotation.name());
        System.out.println("value: " + myAnnotation.value());
    }
  }
}

Notice how the Method.getParameterAnnotations() method returns a two-dimensional Annotation array, containing an array of annotations for each method parameter.

Field Annotations

Here is an example of a field with annotations:

public class TheClass {

  @MyAnnotation(name="someName",  value = "Hello World")
  public String myField = null;
}

You can access field annotations like this:

Field field = ... //obtain field object
Annotation[] annotations = field.getDeclaredAnnotations();

for(Annotation annotation : annotations){
    if(annotation instanceof MyAnnotation){
        MyAnnotation myAnnotation = (MyAnnotation) annotation;
        System.out.println("name: " + myAnnotation.name());
        System.out.println("value: " + myAnnotation.value());
    }
}

You can also access a specific field annotation like this:

Field field = ... // obtain method object
Annotation annotation = field.getAnnotation(MyAnnotation.class);

if(annotation instanceof MyAnnotation){
    MyAnnotation myAnnotation = (MyAnnotation) annotation;
    System.out.println("name: " + myAnnotation.name());
    System.out.println("value: " + myAnnotation.value());
}

출처 - http://tutorials.jenkov.com/java-reflection/annotations.html


'Language > JAVA' 카테고리의 다른 글

Java Reflection - Arrays  (0) 2014.12.01
Java Reflection - Generics  (0) 2014.12.01
Java Reflection - Private Fields and Methods  (0) 2014.12.01
Java Reflection - Getters and Setters  (0) 2014.12.01
Java Reflection - Methods  (0) 2014.12.01
: