@Override
	public void importData(JsonReader reader) throws IOException {

		logger.info("Reading configuration for 1.3");

		// this *HAS* to start as an object
		reader.beginObject();

		while (reader.hasNext()) {
			JsonToken tok = reader.peek();
			switch (tok) {
				case NAME:
					String name = reader.nextName();
					// find out which member it is
					if (name.equals(CLIENTS)) {
						readClients(reader);
					} else if (name.equals(GRANTS)) {
						readGrants(reader);
					} else if (name.equals(WHITELISTEDSITES)) {
						readWhitelistedSites(reader);
					} else if (name.equals(BLACKLISTEDSITES)) {
						readBlacklistedSites(reader);
					} else if (name.equals(AUTHENTICATIONHOLDERS)) {
						readAuthenticationHolders(reader);
					} else if (name.equals(ACCESSTOKENS)) {
						readAccessTokens(reader);
					} else if (name.equals(REFRESHTOKENS)) {
						readRefreshTokens(reader);
					} else if (name.equals(SYSTEMSCOPES)) {
						readSystemScopes(reader);
					} else {
						boolean processed = false;
						for (MITREidDataServiceExtension extension : extensions) {
							if (extension.supportsVersion(THIS_VERSION)) {
								processed = extension.importExtensionData(name, reader);
								if (processed) {
									// if the extension processed data, break out of this inner loop
									// (only the first extension to claim an extension point gets it)
									break;
								}
							}
						}
						if (!processed) {
							// unknown token, skip it
							reader.skipValue();
						}
					}
					break;
				case END_OBJECT:
					// the object ended, we're done here
					reader.endObject();
					continue;
				default:
					logger.debug("Found unexpected entry");
					reader.skipValue();
					continue;
			}
		}
		fixObjectReferences();
		for (MITREidDataServiceExtension extension : extensions) {
			if (extension.supportsVersion(THIS_VERSION)) {
				extension.fixExtensionObjectReferences(maps);
				break;
			}
		}
		maps.clearAll();
	}
@Test
	public void testImportGrants() throws IOException, ParseException {
		Date creationDate1 = formatter.parse("2014-09-10T22:49:44.090+00:00", Locale.ENGLISH);
		Date accessDate1 = formatter.parse("2014-09-10T23:49:44.090+00:00", Locale.ENGLISH);

		OAuth2AccessTokenEntity mockToken1 = mock(OAuth2AccessTokenEntity.class);
		when(mockToken1.getId()).thenReturn(1L);

		ApprovedSite site1 = new ApprovedSite();
		site1.setId(1L);
		site1.setClientId("foo");
		site1.setCreationDate(creationDate1);
		site1.setAccessDate(accessDate1);
		site1.setUserId("user1");
		site1.setAllowedScopes(ImmutableSet.of("openid", "phone"));
		when(mockToken1.getApprovedSite()).thenReturn(site1);

		Date creationDate2 = formatter.parse("2014-09-11T18:49:44.090+00:00", Locale.ENGLISH);
		Date accessDate2 = formatter.parse("2014-09-11T20:49:44.090+00:00", Locale.ENGLISH);
		Date timeoutDate2 = formatter.parse("2014-10-01T20:49:44.090+00:00", Locale.ENGLISH);

		ApprovedSite site2 = new ApprovedSite();
		site2.setId(2L);
		site2.setClientId("bar");
		site2.setCreationDate(creationDate2);
		site2.setAccessDate(accessDate2);
		site2.setUserId("user2");
		site2.setAllowedScopes(ImmutableSet.of("openid", "offline_access", "email", "profile"));
		site2.setTimeoutDate(timeoutDate2);

		String configJson = "{" +
				"\"" + MITREidDataService.CLIENTS + "\": [], " +
				"\"" + MITREidDataService.ACCESSTOKENS + "\": [], " +
				"\"" + MITREidDataService.REFRESHTOKENS + "\": [], " +
				"\"" + MITREidDataService.WHITELISTEDSITES + "\": [], " +
				"\"" + MITREidDataService.BLACKLISTEDSITES + "\": [], " +
				"\"" + MITREidDataService.SYSTEMSCOPES + "\": [], " +
				"\"" + MITREidDataService.AUTHENTICATIONHOLDERS + "\": [], " +
				"\"" + MITREidDataService.GRANTS + "\": [" +

				"{\"id\":1,\"clientId\":\"foo\",\"creationDate\":\"2014-09-10T22:49:44.090+00:00\",\"accessDate\":\"2014-09-10T23:49:44.090+00:00\","
				+ "\"userId\":\"user1\",\"whitelistedSiteId\":null,\"allowedScopes\":[\"openid\",\"phone\"], \"whitelistedSiteId\":1,"
				+ "\"approvedAccessTokens\":[1]}," +
				"{\"id\":2,\"clientId\":\"bar\",\"creationDate\":\"2014-09-11T18:49:44.090+00:00\",\"accessDate\":\"2014-09-11T20:49:44.090+00:00\","
				+ "\"timeoutDate\":\"2014-10-01T20:49:44.090+00:00\",\"userId\":\"user2\","
				+ "\"allowedScopes\":[\"openid\",\"offline_access\",\"email\",\"profile\"]}" +

				"  ]" +
				"}";

		logger.debug(configJson);

		JsonReader reader = new JsonReader(new StringReader(configJson));

		final Map<Long, ApprovedSite> fakeDb = new HashMap<>();
		when(approvedSiteRepository.save(isA(ApprovedSite.class))).thenAnswer(new Answer<ApprovedSite>() {
			Long id = 364L;
			@Override
			public ApprovedSite answer(InvocationOnMock invocation) throws Throwable {
				ApprovedSite _site = (ApprovedSite) invocation.getArguments()[0];
				if(_site.getId() == null) {
					_site.setId(id++);
				}
				fakeDb.put(_site.getId(), _site);
				return _site;
			}
		});
		when(approvedSiteRepository.getById(anyLong())).thenAnswer(new Answer<ApprovedSite>() {
			@Override
			public ApprovedSite answer(InvocationOnMock invocation) throws Throwable {
				Long _id = (Long) invocation.getArguments()[0];
				return fakeDb.get(_id);
			}
		});
		when(wlSiteRepository.getById(isNull(Long.class))).thenAnswer(new Answer<WhitelistedSite>() {
			Long id = 432L;
			@Override
			public WhitelistedSite answer(InvocationOnMock invocation) throws Throwable {
				WhitelistedSite _site = mock(WhitelistedSite.class);
				when(_site.getId()).thenReturn(id++);
				return _site;
			}
		});
		when(tokenRepository.getAccessTokenById(isNull(Long.class))).thenAnswer(new Answer<OAuth2AccessTokenEntity>() {
			Long id = 245L;
			@Override
			public OAuth2AccessTokenEntity answer(InvocationOnMock invocation) throws Throwable {
				OAuth2AccessTokenEntity _token = mock(OAuth2AccessTokenEntity.class);
				when(_token.getId()).thenReturn(id++);
				return _token;
			}
		});

		dataService.importData(reader);
		//2 for sites, 1 for updating access token ref on #1
		verify(approvedSiteRepository, times(3)).save(capturedApprovedSites.capture());

		List<ApprovedSite> savedSites = new ArrayList(fakeDb.values());

		assertThat(savedSites.size(), is(2));

		assertThat(savedSites.get(0).getClientId(), equalTo(site1.getClientId()));
		assertThat(savedSites.get(0).getAccessDate(), equalTo(site1.getAccessDate()));
		assertThat(savedSites.get(0).getCreationDate(), equalTo(site1.getCreationDate()));
		assertThat(savedSites.get(0).getAllowedScopes(), equalTo(site1.getAllowedScopes()));
		assertThat(savedSites.get(0).getTimeoutDate(), equalTo(site1.getTimeoutDate()));

		assertThat(savedSites.get(1).getClientId(), equalTo(site2.getClientId()));
		assertThat(savedSites.get(1).getAccessDate(), equalTo(site2.getAccessDate()));
		assertThat(savedSites.get(1).getCreationDate(), equalTo(site2.getCreationDate()));
		assertThat(savedSites.get(1).getAllowedScopes(), equalTo(site2.getAllowedScopes()));
		assertThat(savedSites.get(1).getTimeoutDate(), equalTo(site2.getTimeoutDate()));
	}